diff --git a/src/docs/asciidoc/core/core-aop-api.adoc b/src/docs/asciidoc/core/core-aop-api.adoc index c1f75e0aae..fe52c91237 100644 --- a/src/docs/asciidoc/core/core-aop-api.adoc +++ b/src/docs/asciidoc/core/core-aop-api.adoc @@ -29,7 +29,6 @@ target different advice with the same pointcut. The `org.springframework.aop.Pointcut` interface is the central interface, used to target advices to particular classes and methods. The complete interface follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -41,7 +40,6 @@ target advices to particular classes and methods. The complete interface follows } ---- -==== Splitting the `Pointcut` interface into two parts allows reuse of class and method matching parts and fine-grained composition operations (such as performing a "`union`" @@ -51,7 +49,6 @@ The `ClassFilter` interface is used to restrict the pointcut to a given set of t classes. If the `matches()` method always returns true, all target classes are matched. The following listing shows the `ClassFilter` interface definition: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -60,11 +57,9 @@ matched. The following listing shows the `ClassFilter` interface definition: boolean matches(Class clazz); } ---- -==== The `MethodMatcher` interface is normally more important. The complete interface follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -77,7 +72,6 @@ The `MethodMatcher` interface is normally more important. The complete interface boolean matches(Method m, Class targetClass, Object[] args); } ---- -==== The `matches(Method, Class)` method is used to test whether this pointcut ever matches a given method on a target class. This evaluation can be performed when an AOP @@ -153,7 +147,6 @@ effectively the union of these pointcuts.) The following example shows how to use `JdkRegexpMethodPointcut`: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -167,7 +160,6 @@ The following example shows how to use `JdkRegexpMethodPointcut`: ---- -==== Spring provides a convenience class named `RegexpMethodPointcutAdvisor`, which lets us also reference an `Advice` (remember that an `Advice` can be an interceptor, before advice, @@ -175,7 +167,6 @@ throws advice, and others). Behind the scenes, Spring uses a `JdkRegexpMethodPoi Using `RegexpMethodPointcutAdvisor` simplifies wiring, as the one bean encapsulates both pointcut and advice, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -192,7 +183,6 @@ pointcut and advice, as the following example shows: ---- -==== You can use `RegexpMethodPointcutAdvisor` with any `Advice` type. @@ -239,7 +229,6 @@ Because static pointcuts are most useful, you should probably subclass abstract method (although you can override other methods to customize behavior). The following example shows how to subclass `StaticMethodMatcherPointcut`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -250,7 +239,6 @@ following example shows how to subclass `StaticMethodMatcherPointcut`: } } ---- -==== There are also superclasses for dynamic pointcuts. @@ -313,7 +301,6 @@ Spring is compliant with the AOP `Alliance` interface for around advice that use interception. Classes that implement `MethodInterceptor` and that implement around advice should also implement the following interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -322,7 +309,6 @@ following interface: Object invoke(MethodInvocation invocation) throws Throwable; } ---- -==== The `MethodInvocation` argument to the `invoke()` method exposes the method being invoked, the target join point, the AOP proxy, and the arguments to the method. The @@ -331,7 +317,6 @@ point. The following example shows a simple `MethodInterceptor` implementation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -345,7 +330,6 @@ The following example shows a simple `MethodInterceptor` implementation: } } ---- -==== Note the call to the `proceed()` method of `MethodInvocation`. This proceeds down the interceptor chain towards the join point. Most interceptors invoke this method and @@ -374,7 +358,6 @@ interceptor chain. The following listing shows the `MethodBeforeAdvice` interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -383,7 +366,6 @@ The following listing shows the `MethodBeforeAdvice` interface: void before(Method m, Object[] args, Object target) throws Throwable; } ---- -==== (Spring's API design would allow for field before advice, although the usual objects apply to field interception and it is @@ -398,7 +380,6 @@ wrapped in an unchecked exception by the AOP proxy. The following example shows a before advice in Spring, which counts all method invocations: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -415,7 +396,6 @@ The following example shows a before advice in Spring, which counts all method i } } ---- -==== TIP: Before advice can be used with any pointcut. @@ -429,13 +409,11 @@ an exception. Spring offers typed throws advice. Note that this means that the tag interface identifying that the given object implements one or more typed throws advice methods. These should be in the following form: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- afterThrowing([Method, args, target], subclassOfThrowable) ---- -==== Only the last argument is required. The method signatures may have either one or four arguments, depending on whether the advice method is interested in the method and @@ -443,7 +421,6 @@ arguments. The next two listing show classes that are examples of throws advice. The following advice is invoked if a `RemoteException` is thrown (including from subclasses): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -454,13 +431,11 @@ The following advice is invoked if a `RemoteException` is thrown (including from } } ---- -==== Unlike the preceding advice, the next example declares four arguments, so that it has access to the invoked method, method arguments, and target object. The following advice is invoked if a `ServletException` is thrown: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -471,13 +446,11 @@ arguments, and target object. The following advice is invoked if a `ServletExcep } } ---- -==== The final example illustrates how these two methods could be used in a single class that handles both `RemoteException` and `ServletException`. Any number of throws advice methods can be combined in a single class. The following listing shows the final example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -492,7 +465,6 @@ methods can be combined in a single class. The following listing shows the final } } ---- -==== NOTE: If a throws-advice method throws an exception itself, it overrides the original exception (that is, it changes the exception thrown to the user). The overriding @@ -511,7 +483,6 @@ TIP: Throws advice can be used with any pointcut. An after returning advice in Spring must implement the `org.springframework.aop.AfterReturningAdvice` interface, which the following listing shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -521,7 +492,6 @@ An after returning advice in Spring must implement the throws Throwable; } ---- -==== An after returning advice has access to the return value (which it cannot modify), the invoked method, the method's arguments, and the target. @@ -529,7 +499,6 @@ the invoked method, the method's arguments, and the target. The following after returning advice counts all successful method invocations that have not thrown exceptions: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -547,7 +516,6 @@ not thrown exceptions: } } ---- -==== This advice does not change the execution path. If it throws an exception, it is thrown up the interceptor chain instead of the return value. @@ -563,7 +531,6 @@ Spring treats introduction advice as a special kind of interception advice. Introduction requires an `IntroductionAdvisor` and an `IntroductionInterceptor` that implement the following interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -572,7 +539,6 @@ implement the following interface: boolean implementsInterface(Class intf); } ---- -==== The `invoke()` method inherited from the AOP Alliance `MethodInterceptor` interface must implement the introduction. That is, if the invoked method is on an introduced @@ -583,7 +549,6 @@ Introduction advice cannot be used with any pointcut, as it applies only at the rather than the method, level. You can only use introduction advice with the `IntroductionAdvisor`, which has the following methods: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -599,7 +564,6 @@ rather than the method, level. You can only use introduction advice with the Class[] getInterfaces(); } ---- -==== There is no `MethodMatcher` and, hence, no `Pointcut` associated with introduction advice. Only class filtering is logical. @@ -612,7 +576,6 @@ introduced interfaces can be implemented by the configured `IntroductionIntercep Consider an example from the Spring test suite and suppose we want to introduce the following interface to one or more objects: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -622,7 +585,6 @@ introduce the following interface to one or more objects: boolean locked(); } ---- -==== This illustrates a mixin. We want to be able to cast advised objects to `Lockable`, whatever their type and call lock and unlock methods. If we call the `lock()` method, we @@ -659,7 +621,6 @@ to that held in the target object. The following example shows the example `LockMixin` class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -688,7 +649,6 @@ The following example shows the example `LockMixin` class: } ---- -==== Often, you need not override the `invoke()` method. The `DelegatingIntroductionInterceptor` implementation (which calls the `delegate` method if @@ -703,7 +663,6 @@ interceptor (which would be defined as a prototype). In this case, there is no configuration relevant for a `LockMixin`, so we create it by using `new`. The following example shows our `LockMixinAdvisor` class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -714,7 +673,6 @@ The following example shows our `LockMixinAdvisor` class: } } ---- -==== We can apply this advisor very simply, because it requires no configuration. (However, it is impossible to use an `IntroductionInterceptor` without an @@ -904,7 +862,6 @@ Consider a simple example of `ProxyFactoryBean` in action. This example involves The following listing shows the example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -933,7 +890,6 @@ The following listing shows the example: ---- -==== Note that the `interceptorNames` property takes a list of `String`, which holds the bean names of the interceptors or advisors in the current factory. You can use advisors, interceptors, before, after @@ -948,18 +904,15 @@ an instance of the prototype from the factory. Holding a reference is not suffic The `person` bean definition shown earlier can be used in place of a `Person` implementation, as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- Person person = (Person) factory.getBean("person"); ---- -==== Other beans in the same IoC context can express a strongly typed dependency on it, as with an ordinary Java object. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -967,7 +920,6 @@ with an ordinary Java object. The following example shows how to do so: ---- -==== The `PersonUser` class in this example exposes a property of type `Person`. As far as it is concerned, the AOP proxy can be used transparently in place of a "`real`" person @@ -979,7 +931,6 @@ inner bean. Only the `ProxyFactoryBean` definition is different. The advice is included only for completeness. The following example shows how to use an anonymous inner bean: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1006,7 +957,6 @@ anonymous inner bean: ---- -==== Using an anonymous inner bean has the advantage that there is only one object of type `Person`. This is useful if we want to prevent users of the application context from obtaining a reference to the un-advised @@ -1060,7 +1010,6 @@ the part before the asterisk are added to the advisor chain. This can come in ha if you need to add a standard set of "`global`" advisors. The following example defines two global advisors: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1076,7 +1025,6 @@ two global advisors: ---- -==== @@ -1090,7 +1038,6 @@ definitions, can result in much cleaner and more concise proxy definitions. First, we create a parent, template, bean definition for the proxy, as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1104,14 +1051,12 @@ First, we create a parent, template, bean definition for the proxy, as follows: ---- -==== This is never instantiated itself, so it can actually be incomplete. Then, each proxy that needs to be created is a child bean definition, which wraps the target of the proxy as an inner bean definition, since the target is never used on its own anyway. The following example shows such a child bean: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1122,12 +1067,10 @@ The following example shows such a child bean: ---- -==== You can override properties from the parent template. In the following example, we override the transaction propagation settings: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1146,7 +1089,6 @@ we override the transaction propagation settings: ---- -==== Note that in the parent bean example, we explicitly marked the parent bean definition as being abstract by setting the `abstract` attribute to `true`, as described @@ -1171,7 +1113,6 @@ The interfaces implemented by the target object are automatically proxied. The following listing shows creation of a proxy for a target object, with one interceptor and one advisor: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1180,7 +1121,6 @@ interceptor and one advisor: factory.addAdvisor(myAdvisor); MyBusinessInterface tb = (MyBusinessInterface) factory.getProxy(); ---- -==== The first step is to construct an object of type `org.springframework.aop.framework.ProxyFactory`. You can create this with a target @@ -1211,7 +1151,6 @@ However you create AOP proxies, you can manipulate them BY using the interface, no matter which other interfaces it implements. This interface includes the following methods: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1235,7 +1174,6 @@ following methods: boolean isFrozen(); ---- -==== The `getAdvisors()` method returns an `Advisor` for every advisor, interceptor, or other advice type that has been added to the factory. If you added an `Advisor`, the @@ -1257,7 +1195,6 @@ change. (You can obtain a new proxy from the factory to avoid this problem.) The following example shows casting an AOP proxy to the `Advised` interface and examining and manipulating its advice: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1276,7 +1213,6 @@ manipulating its advice: assertEquals("Added two advisors", oldAdvisorCount + 2, advised.getAdvisors().length); ---- -==== NOTE: It is questionable whether it is advisable (no pun intended) to modify advice on a business object in production, although there are, no doubt, legitimate usage cases. @@ -1333,7 +1269,6 @@ The `BeanNameAutoProxyCreator` class is a `BeanPostProcessor` that automatically AOP proxies for beans with names that match literal values or wildcards. The following example shows how to create a `BeanNameAutoProxyCreator` bean: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1346,7 +1281,6 @@ example shows how to create a `BeanNameAutoProxyCreator` bean: ---- -==== As with `ProxyFactoryBean`, there is an `interceptorNames` property rather than a list of interceptors, to allow correct behavior for prototype advisors. Named "`interceptors`" @@ -1398,7 +1332,6 @@ bean`" idiom shown earlier also offers this benefit.) The following example creates a `DefaultAdvisorAutoProxyCreator` bean and the other elements discussed in this section: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1416,7 +1349,6 @@ elements discussed in this section: ---- -==== The `DefaultAdvisorAutoProxyCreator` is very useful if you want to apply the same advice consistently to many business objects. Once the infrastructure definitions are in place, @@ -1470,18 +1402,15 @@ Changing the target source's target takes effect immediately. The You can change the target by using the `swap()` method on HotSwappableTargetSource, as the follow example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- HotSwappableTargetSource swapper = (HotSwappableTargetSource) beanFactory.getBean("swapper"); Object oldTarget = swapper.swap(newTarget); ---- -==== The following example shows the required XML definitions: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1495,7 +1424,6 @@ The following example shows the required XML definitions: ---- -==== The preceding `swap()` call changes the target of the swappable bean. Clients that hold a reference to that bean are unaware of the change but immediately start hitting @@ -1528,7 +1456,6 @@ NOTE: Commons Pool 1.5+ is also supported but is deprecated as of Spring Framewo The following listing shows an example configuration: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1547,7 +1474,6 @@ The following listing shows an example configuration: ---- -==== Note that the target object (`businessObjectTarget` in the preceding example) must be a prototype. This lets the `PoolingTargetSource` implementation create new instances @@ -1565,7 +1491,6 @@ You can configure Spring to be able to cast any pooled object to the about the configuration and current size of the pool through an introduction. You need to define an advisor similar to the following: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1574,7 +1499,6 @@ need to define an advisor similar to the following: ---- -==== This advisor is obtained by calling a convenience method on the `AbstractPoolingTargetSource` class, hence the use of `MethodInvokingFactoryBean`. This @@ -1583,14 +1507,12 @@ the `ProxyFactoryBean` that exposes the pooled object. The cast is defined as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- PoolingConfig conf = (PoolingConfig) beanFactory.getBean("businessObject"); System.out.println("Max pool size is " + conf.getMaxSize()); ---- -==== NOTE: Pooling stateless service objects is not usually necessary. We do not believe it should be the default choice, as most stateless objects are naturally thread safe, and instance @@ -1613,7 +1535,6 @@ use this approach without very good reason. To do this, you could modify the `poolTargetSource` definition shown earlier as follows (we also changed the name, for clarity): -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1621,7 +1542,6 @@ To do this, you could modify the `poolTargetSource` definition shown earlier as ---- -==== The only property is the name of the target bean. Inheritance is used in the `TargetSource` implementations to ensure consistent naming. As with the pooling target @@ -1638,7 +1558,6 @@ facility to transparently store a resource alongside a thread. Setting up a `ThreadLocalTargetSource` is pretty much the same as was explained for the other types of target source, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1646,7 +1565,6 @@ of target source, as the following example shows: ---- -==== NOTE: `ThreadLocal` instances come with serious issues (potentially resulting in memory leaks) when incorrectly using them in multi-threaded and multi-classloader environments. You diff --git a/src/docs/asciidoc/core/core-aop.adoc b/src/docs/asciidoc/core/core-aop.adoc index 83ad5afdf9..6e725c080b 100644 --- a/src/docs/asciidoc/core/core-aop.adoc +++ b/src/docs/asciidoc/core/core-aop.adoc @@ -235,7 +235,6 @@ classpath of your application (version 1.8 or later). This library is available To enable @AspectJ support with Java `@Configuration`, add the `@EnableAspectJAutoProxy` annotation, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -245,7 +244,6 @@ annotation, as the following example shows: } ---- -==== [[aop-enable-aspectj-xml]] @@ -254,13 +252,11 @@ annotation, as the following example shows: To enable @AspectJ support with XML-based configuration, use the `aop:aspectj-autoproxy` element, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== This assumes that you use schema support as described in <>. See @@ -280,7 +276,6 @@ minimal definition required for a not-very-useful aspect. The first of the two example shows a regular bean definition in the application context that points to a bean class that has the `@Aspect` annotation: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -288,12 +283,10 @@ the `@Aspect` annotation: ---- -==== The second of the two examples shows the `NotVeryUsefulAspect` class definition, which is annotated with the `org.aspectj.lang.annotation.Aspect` annotation; -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -305,7 +298,6 @@ the `org.aspectj.lang.annotation.Aspect` annotation; } ---- -==== Aspects (classes annotated with `@Aspect`) can have methods and fields, the same as any other class. They can also contain pointcut, advice, and introduction (inter-type) @@ -343,14 +335,12 @@ An example may help make this distinction between a pointcut signature and a poi expression clear. The following example defines a pointcut named `anyOldTransfer` that matches the execution of any method named `transfer`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @Pointcut("execution(* transfer(..))")// the pointcut expression private void anyOldTransfer() {}// the pointcut signature ---- -==== The pointcut expression that forms the value of the `@Pointcut` annotation is a regular AspectJ 5 pointcut expression. For a full discussion of AspectJ's pointcut language, see @@ -433,13 +423,11 @@ Spring AOP also supports an additional PCD named `bean`. This PCD lets you limit the matching of join points to a particular named Spring bean or to a set of named Spring beans (when using wildcards). The `bean` PCD has the following form: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- bean(idOrNameOfBean) ---- -==== The `idOrNameOfBean` token can be the name of any Spring bean. Limited wildcard support that uses the `*` character is provided, so, if you establish some naming @@ -468,7 +456,6 @@ You can combine pointcut expressions can be combined by using `&&,` `||` and `!` refer to pointcut expressions by name. The following example shows three pointcut expressions: -==== [source,java,indent=0] [subs="verbatim"] ---- @@ -486,7 +473,7 @@ of any public method. <2> `inTrading` matches if a method execution is in the trading module. <3> `tradingOperation` matches if a method execution represents any public method in the trading module. -==== + It is a best practice to build more complex pointcut expressions out of smaller named components, as shown earlier. When referring to pointcuts by name, normal Java visibility @@ -503,7 +490,6 @@ application and particular sets of operations from within several aspects. We re defining a "`SystemArchitecture`" aspect that captures common pointcut expressions for this purpose. Such an aspect typically resembles the following example: -==== [source,java,indent=0] [subs="verbatim"] ---- @@ -566,13 +552,11 @@ this purpose. Such an aspect typically resembles the following example: } ---- -==== You can refer to the pointcuts defined in such an aspect anywhere you need a pointcut expression. For example, to make the service layer transactional, you could write the following: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -588,7 +572,6 @@ write the following: ---- -==== The `` and `` elements are discussed in <>. The transaction elements are discussed in <>. @@ -600,14 +583,12 @@ transaction elements are discussed in <> for how to make the proxy object available in the advice body. @@ -715,13 +680,11 @@ for how to make the proxy object available in the advice body. * Any join point (method execution only in Spring AOP) where the target object implements the `AccountService` interface: + -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- target(com.xyz.service.AccountService) ---- -==== + NOTE: 'target' is more commonly used in a binding form. See the <> section for how to make the target object available in the advice body. @@ -729,13 +692,11 @@ for how to make the target object available in the advice body. * Any join point (method execution only in Spring AOP) that takes a single parameter and where the argument passed at runtime is `Serializable`: + -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- args(java.io.Serializable) ---- -==== + NOTE: 'args' is more commonly used in a binding form. See the <> section for how to make the method arguments available in the advice body. @@ -748,13 +709,11 @@ parameter of type `Serializable`. * Any join point (method execution only in Spring AOP) where the target object has a `@Transactional` annotation: + -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @target(org.springframework.transaction.annotation.Transactional) ---- -==== + NOTE: You can also use '@target' in a binding form. See the <> section for how to make the annotation object available in the advice body. @@ -762,13 +721,11 @@ how to make the annotation object available in the advice body. * Any join point (method execution only in Spring AOP) where the declared type of the target object has an `@Transactional` annotation: + -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @within(org.springframework.transaction.annotation.Transactional) ---- -==== + NOTE: You can also use '@within' in a binding form. See the <> section for how to make the annotation object available in the advice body. @@ -776,13 +733,11 @@ how to make the annotation object available in the advice body. * Any join point (method execution only in Spring AOP) where the executing method has an `@Transactional` annotation: + -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @annotation(org.springframework.transaction.annotation.Transactional) ---- -==== + NOTE: You can also use '@annotation' in a binding form. See the <> section for how to make the annotation object available in the advice body. @@ -790,13 +745,11 @@ for how to make the annotation object available in the advice body. * Any join point (method execution only in Spring AOP) which takes a single parameter, and where the runtime type of the argument passed has the `@Classified` annotation: + -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @args(com.xyz.security.Classified) ---- -==== + NOTE: You can also use '@args' in a binding form. See the <> section how to make the annotation object(s) available in the advice body. @@ -804,24 +757,20 @@ how to make the annotation object(s) available in the advice body. * Any join point (method execution only in Spring AOP) on a Spring bean named `tradeService`: + -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- bean(tradeService) ---- -==== * Any join point (method execution only in Spring AOP) on Spring beans having names that match the wildcard expression `*Service`: + -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- bean(*Service) ---- -==== [[writing-good-pointcuts]] @@ -875,7 +824,6 @@ simple reference to a named pointcut or a pointcut expression declared in place. You can declare before advice in an aspect by using the `@Before` annotation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -892,12 +840,10 @@ You can declare before advice in an aspect by using the `@Before` annotation: } ---- -==== If we use an in-place pointcut expression, we could rewrite the preceding example as the following example: -==== [source,java,indent=0] [subs="verbatim"] ---- @@ -914,7 +860,6 @@ following example: } ---- -==== [[aop-advice-after-returning]] @@ -923,7 +868,6 @@ following example: After returning advice runs when a matched method execution returns normally. You can declare it by using the `@AfterReturning` annotation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -940,7 +884,6 @@ declare it by using the `@AfterReturning` annotation: } ---- -==== NOTE: You can have multiple advice declarations (and other members as well), all inside the same aspect. We show only a single advice declaration in @@ -950,7 +893,6 @@ Sometimes, you need access in the advice body to the actual value that was retur can use the form of `@AfterReturning` that binds the return value to get that access, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -969,7 +911,6 @@ the following example shows: } ---- -==== The name used in the `returning` attribute must correspond to the name of a parameter in the advice method. When a method execution returns, the return value is passed to @@ -988,7 +929,6 @@ After throwing advice runs when a matched method execution exits by throwing an exception. You can declare it by using the `@AfterThrowing` annotation, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1005,7 +945,6 @@ example shows: } ---- -==== Often, you want the advice to run only when exceptions of a given type are thrown, and you also often need access to the thrown exception in the advice body. You can use the @@ -1013,7 +952,6 @@ you also often need access to the thrown exception in the advice body. You can u exception type otherwise) and bind the thrown exception to an advice parameter. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1032,7 +970,6 @@ following example shows how to do so: } ---- -==== The name used in the `throwing` attribute must correspond to the name of a parameter in the advice method. When a method execution exits by throwing an exception, the exception @@ -1049,7 +986,6 @@ using the `@After` annotation. After advice must be prepared to handle both norm exception return conditions. It is typically used for releasing resources and similar purposes. The following example shows how to use after finally advice: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1066,7 +1002,6 @@ The following example shows how to use after finally advice: } ---- -==== [[aop-ataspectj-around-advice]] @@ -1102,7 +1037,6 @@ parameters>>. The following example shows how to use around advice: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1123,7 +1057,6 @@ The following example shows how to use around advice: } ---- -==== The value returned by the around advice is the return value seen by the caller of the method. For example, a simple caching aspect could return a value from a cache if it @@ -1170,7 +1103,6 @@ clearer. Suppose you want to advise the execution of DAO operations that take an object as the first parameter, and you need access to the account in the advice body. You could write the following: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1179,7 +1111,6 @@ You could write the following: // ... } ---- -==== The `args(account,..)` part of the pointcut expression serves two purposes. First, it restricts matching to only those method executions where the method takes at least one @@ -1191,7 +1122,6 @@ Another way of writing this is to declare a pointcut that "`provides`" the `Acco object value when it matches a join point, and then refer to the named pointcut from the advice. This would look as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1203,7 +1133,6 @@ from the advice. This would look as follows: // ... } ---- -==== See the AspectJ programming guide for more details. @@ -1215,7 +1144,6 @@ examples show how to match the execution of methods annotated with an The first of the two examples shows the definition of the `@Auditable` annotation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1225,11 +1153,9 @@ The first of the two examples shows the definition of the `@Auditable` annotatio AuditCode value(); } ---- -==== The second of the two examples shows the advice that matches the execution of `@Auditable` methods: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1239,7 +1165,6 @@ The second of the two examples shows the advice that matches the execution of `@ // ... } ---- -==== [[aop-ataspectj-advice-params-generics]] ===== Advice Parameters and Generics @@ -1247,7 +1172,6 @@ The second of the two examples shows the advice that matches the execution of `@ Spring AOP can handle generics used in class declarations and method parameters. Suppose you have a generic type like the following: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1256,12 +1180,10 @@ you have a generic type like the following: void sampleGenericCollectionMethod(Collection param); } ---- -==== You can restrict interception of method types to certain parameter types by typing the advice parameter to the parameter type for which you want to intercept the method: -==== [source,java,indent=0] [subs="verbatim"] ---- @@ -1270,12 +1192,10 @@ typing the advice parameter to the parameter type for which you want to intercep // Advice implementation } ---- -==== This approach does not work for generic collections. So you cannot define a pointcut as follows: -==== [source,java,indent=0] [subs="verbatim"] ---- @@ -1284,7 +1204,6 @@ pointcut as follows: // Advice implementation } ---- -==== To make this work, we would have to inspect every element of the collection, which is not reasonable, as we also cannot decide how to treat `null` values in general. To achieve @@ -1305,7 +1224,6 @@ following strategy to determine parameter names: the annotated method. These argument names are available at runtime. The following example shows how to use the `argNames` attribute: + -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1316,14 +1234,12 @@ following strategy to determine parameter names: // ... use code and bean } ---- -==== + If the first parameter is of the `JoinPoint`, `ProceedingJoinPoint`, or `JoinPoint.StaticPart` type, you ca leave out the name of the parameter from the value of the `argNames` attribute. For example, if you modify the preceding advice to receive the join point object, the `argNames` attribute need not include it: + -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1334,7 +1250,6 @@ the join point object, the `argNames` attribute need not include it: // ... use code, bean, and jp } ---- -==== + The special treatment given to the first parameter of the `JoinPoint`, `ProceedingJoinPoint`, and `JoinPoint.StaticPart` types is particularly convenient for @@ -1342,7 +1257,6 @@ advice instances that do not collect any other join point context. In such situa omit the `argNames` attribute. For example, the following advice need not declare the `argNames` attribute: + -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1351,7 +1265,6 @@ the `argNames` attribute: // ... use jp } ---- -==== * Using the `'argNames'` attribute is a little clumsy, so if the `'argNames'` attribute has not been specified, Spring AOP looks at the debug information for the @@ -1383,7 +1296,6 @@ arguments that works consistently across Spring AOP and AspectJ. The solution is to ensure that the advice signature binds each of the method parameters in order. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1396,7 +1308,6 @@ The following example shows how to do so: return pjp.proceed(new Object[] {newPattern}); } ---- -==== In many cases, you do this binding anyway (as in the preceding example). @@ -1440,7 +1351,6 @@ interface named `UsageTracked` and an implementation of that interface named `De the following aspect declares that all implementors of service interfaces also implement the `UsageTracked` interface (to expose statistics via JMX for example): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1457,7 +1367,6 @@ the `UsageTracked` interface (to expose statistics via JMX for example): } ---- -==== The interface to be implemented is determined by the type of the annotated field. The `value` attribute of the `@DeclareParents` annotation is an AspectJ type pattern. Any @@ -1466,13 +1375,11 @@ before advice of the preceding example, service beans can be directly used as implementations of the `UsageTracked` interface. If accessing a bean programmatically, you would write the following: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- UsageTracked usageTracked = (UsageTracked) context.getBean("myService"); ---- -==== @@ -1491,7 +1398,6 @@ supported). You can declare a `perthis` aspect by specifying a `perthis` clause in the `@Aspect` annotation. Consider the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1507,7 +1413,6 @@ annotation. Consider the following example: } ---- -==== In the preceding example, the effect of the `'perthis'` clause is that one aspect instance is created for each unique service object that executes a business service (each unique object bound to @@ -1542,7 +1447,6 @@ aspect. Because we want to retry the operation, we need to use around advice so that we can call `proceed` multiple times. The following listing shows the basic aspect implementation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1584,7 +1488,6 @@ call `proceed` multiple times. The following listing shows the basic aspect impl } ---- -==== Note that the aspect implements the `Ordered` interface so that we can set the precedence of the aspect higher than the transaction advice (we want a fresh transaction each time we @@ -1596,7 +1499,6 @@ we have exhausted all of our retry attempts. The corresponding Spring configuration follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1607,12 +1509,10 @@ The corresponding Spring configuration follows: ---- -==== To refine the aspect so that it retries only idempotent operations, we might define the following `Idempotent` annotation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1621,13 +1521,11 @@ To refine the aspect so that it retries only idempotent operations, we might def // marker annotation } ---- -==== We can then use the annotation to annotate the implementation of service operations. The change to the aspect to retry only idempotent operations involves refining the pointcut expression so that only `@Idempotent` operations match, as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1637,7 +1535,6 @@ expression so that only `@Idempotent` operations match, as follows: ... } ---- -==== @@ -1681,7 +1578,6 @@ methods of the object, and the pointcut and advice information are captured in t You can declare an aspect by using the element, and reference the backing bean by using the `ref` attribute, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1695,7 +1591,6 @@ by using the `ref` attribute, as the following example shows: ... ---- -==== The bean that backs the aspect (`aBean` in this case) can of course be configured and dependency injected just like any other Spring bean. @@ -1711,7 +1606,6 @@ definition be shared across several aspects and advisors. A pointcut that represents the execution of any business service in the service layer can be defined as follows: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -1722,7 +1616,6 @@ be defined as follows: ---- -==== Note that the pointcut expression itself is using the same AspectJ pointcut expression language as described in <>. If you use the schema based @@ -1730,7 +1623,6 @@ declaration style, you can refer to named pointcuts defined in types (@Aspects) within the pointcut expression. Another way of defining the above pointcut would be as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1741,14 +1633,12 @@ would be as follows: ---- -==== Assume that you have a `SystemArchitecture` aspect as described in <>. Then declaring a pointcut inside an aspect is very similar to declaring a top-level pointcut, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -1765,13 +1655,11 @@ as the following example shows: ---- -==== In much the same way as an @AspectJ aspect, pointcuts declared by using the schema based definition style can collect join point context. For example, the following pointcut collects the `this` object as the join point context and passes it to the advice: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -1790,12 +1678,10 @@ collects the `this` object as the join point context and passes it to the advice ---- -==== The advice must be declared to receive the collected join point context by including parameters of the matching names, as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1803,13 +1689,11 @@ parameters of the matching names, as follows: ... } ---- -==== When combining pointcut sub-expressions, `&&` is awkward within an XML document, so you can use the `and`, `or`, and `not` keywords in place of `&&`, `||`, and `!`, respectively. For example, the previous pointcut can be better written as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1826,7 +1710,6 @@ respectively. For example, the previous pointcut can be better written as follow ---- -==== Note that pointcuts defined in this way are referred to by their XML `id` and cannot be used as named pointcuts to form composite pointcuts. The named pointcut support in the @@ -1848,7 +1731,6 @@ exactly the same semantics. Before advice runs before a matched method execution. It is declared inside an `` by using the element, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1862,13 +1744,11 @@ Before advice runs before a matched method execution. It is declared inside an ---- -==== Here, `dataAccessOperation` is the `id` of a pointcut defined at the top (``) level. To define the pointcut inline instead, replace the `pointcut-ref` attribute with a `pointcut` attribute, as follows: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -1882,7 +1762,6 @@ a `pointcut` attribute, as follows: ---- -==== As we noted in the discussion of the @AspectJ style, using named pointcuts can significantly improve the readability of your code. @@ -1901,7 +1780,6 @@ After returning advice runs when a matched method execution completes normally. declared inside an `` in the same way as before advice. The following example shows how to declare it: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1915,13 +1793,11 @@ shows how to declare it: ---- -==== As in the @AspectJ style, you can get the return value within the advice body. To do so, use the returning attribute to specify the name of the parameter to which the return value should be passed, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1936,19 +1812,16 @@ the return value should be passed, as the following example shows: ---- -==== The `doAccessCheck` method must declare a parameter named `retVal`. The type of this parameter constrains matching in the same way as described for `@AfterReturning`. For example, you can declare the method signature as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- public void doAccessCheck(Object retVal) {... ---- -==== [[aop-schema-advice-after-throwing]] @@ -1958,7 +1831,6 @@ After throwing advice executes when a matched method execution exits by throwing exception. It is declared inside an `` by using the after-throwing element, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1972,13 +1844,11 @@ as the following example shows: ---- -==== As in the @AspectJ style, you can get the thrown exception within the advice body. To do so, use the throwing attribute to specify the name of the parameter to which the exception should be passed as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1993,19 +1863,16 @@ which the exception should be passed as the following example shows: ---- -==== The `doRecoveryActions` method must declare a parameter named `dataAccessEx`. The type of this parameter constrains matching in the same way as described for `@AfterThrowing`. For example, the method signature may be declared as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- public void doRecoveryActions(DataAccessException dataAccessEx) {... ---- -==== [[aop-schema-advice-after-finally]] @@ -2014,7 +1881,6 @@ example, the method signature may be declared as follows: After (finally) advice runs no matter how a matched method execution exits. You can declare it by using the `after` element, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2028,7 +1894,6 @@ by using the `after` element, as the following example shows: ---- -==== [[aop-schema-advice-around]] @@ -2050,7 +1915,6 @@ in the array are used as the arguments to the method execution when it proceeds. <> for notes on calling `proceed` with an `Object[]`. The following example shows how to declare around advice in XML: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2064,12 +1928,10 @@ The following example shows how to declare around advice in XML: ---- -==== The implementation of the `doBasicProfiling` advice can be exactly the same as in the @AspectJ example (minus the annotation, of course), as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2080,7 +1942,6 @@ The implementation of the `doBasicProfiling` advice can be exactly the same as i return retVal; } ---- -==== [[aop-schema-params]] @@ -2095,7 +1956,6 @@ attribute of the advice element, which is treated in the same manner as the `arg attribute in an advice annotation (as described in <>). The following example shows how to specify an argument name in XML: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2104,14 +1964,12 @@ The following example shows how to specify an argument name in XML: method="audit" arg-names="auditable"/> ---- -==== The `arg-names` attribute accepts a comma-delimited list of parameter names. The following slightly more involved example of the XSD-based approach shows some around advice used in conjunction with a number of strongly typed parameters: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2129,14 +1987,12 @@ some around advice used in conjunction with a number of strongly typed parameter } } ---- -==== Next up is the aspect. Notice the fact that the `profile(..)` method accepts a number of strongly-typed parameters, the first of which happens to be the join point used to proceed with the method call. The presence of this parameter is an indication that the `profile(..)` is to be used as `around` advice, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2159,12 +2015,10 @@ proceed with the method call. The presence of this parameter is an indication th } } ---- -==== Finally, the following example XML configuration effects the execution of the preceding advice for a particular join point: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2196,11 +2050,9 @@ preceding advice for a particular join point: ---- -==== Consider the following driver script: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2217,11 +2069,9 @@ Consider the following driver script: } } ---- -==== With such a Boot class, we would get output similar to the following on standard output: -==== [literal] [subs="verbatim,quotes"] ---- @@ -2231,7 +2081,6 @@ ms % Task name ----------------------------------------- 00000 ? execution(getFoo) ---- -==== [[aop-ordering]] @@ -2258,7 +2107,6 @@ For example, given an interface named `UsageTracked` and an implementation of th interfaces also implement the `UsageTracked` interface. (In order to expose statistics through JMX for example.) -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2276,11 +2124,9 @@ through JMX for example.) ---- -==== The class that backs the `usageTracking` bean would then contain the following method: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2288,7 +2134,6 @@ The class that backs the `usageTracking` bean would then contain the following m usageTracked.incrementUseCount(); } ---- -==== The interface to be implemented is determined by the `implement-interface` attribute. The value of the `types-matching` attribute is an AspectJ type pattern. Any bean of a @@ -2297,13 +2142,11 @@ advice of the preceding example, service beans can be directly used as implement the `UsageTracked` interface. To access a bean programmatically, you could write the following: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- UsageTracked usageTracked = (UsageTracked) context.getBean("myService"); ---- -==== @@ -2328,7 +2171,6 @@ Spring supports the advisor concept with the `` element. You most commonly see it used in conjunction with transactional advice, which also has its own namespace support in Spring. The following example shows an advisor: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -2349,7 +2191,6 @@ namespace support in Spring. The following example shows an advisor: ---- -==== As well as the `pointcut-ref` attribute used in the preceding example, you can also use the `pointcut` attribute to define a pointcut expression inline. @@ -2378,7 +2219,6 @@ Because we want to retry the operation, we need to use around advice so that we call `proceed` multiple times. The following listing shows the basic aspect implementation (which is a regular Java class that uses the schema support): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2418,7 +2258,6 @@ call `proceed` multiple times. The following listing shows the basic aspect impl } ---- -==== Note that the aspect implements the `Ordered` interface so that we can set the precedence of the aspect higher than the transaction advice (we want a fresh transaction each time we @@ -2432,7 +2271,6 @@ annotations removed. The corresponding Spring configuration is as follows: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -2457,14 +2295,12 @@ The corresponding Spring configuration is as follows: ---- -==== Notice that, for the time, being we assume that all business services are idempotent. If this is not the case, we can refine the aspect so that it retries only genuinely idempotent operations, by introducing an `Idempotent` annotation and using the annotation to annotate the implementation of service operations, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2473,13 +2309,11 @@ to annotate the implementation of service operations, as the following example s // marker annotation } ---- -==== The change to the aspect to retry only idempotent operations involves refining the pointcut expression so that only `@Idempotent` operations match, as follows: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -2487,7 +2321,6 @@ pointcut expression so that only `@Idempotent` operations match, as follows: expression="execution(* com.xyz.myapp.service.*.*(..)) and @annotation(com.xyz.myapp.service.Idempotent)"/> ---- -==== @@ -2550,7 +2383,6 @@ it can express than the @AspectJ style: Only the "`singleton`" aspect instantiat is supported, and it is not possible to combine named pointcuts declared in XML. For example, in the @AspectJ style you can write something like the following: -==== [source,java,indent=0] [subs="verbatim"] ---- @@ -2563,7 +2395,6 @@ For example, in the @AspectJ style you can write something like the following: @Pointcut("propertyAccess() && operationReturningAnAccount()") public void accountPropertyAccess() {} ---- -==== In the XML style you can declare the first two pointcuts: @@ -2631,7 +2462,6 @@ so. However, you should consider the following issues: To force the use of CGLIB proxies, set the value of the `proxy-target-class` attribute of the `` element to true, as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2639,19 +2469,16 @@ the `` element to true, as follows: ---- -==== To force CGLIB proxying when you use the @AspectJ auto-proxy support, set the `proxy-target-class` attribute of the `` element to `true`, as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== [NOTE] ==== @@ -2679,7 +2506,6 @@ Consider first the scenario where you have a plain-vanilla, un-proxied, nothing-special-about-it, straight object reference, as the following code snippet shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2695,14 +2521,12 @@ code snippet shows: } } ---- -==== If you invoke a method on an object reference, the method is invoked directly on that object reference, as the following image and listing show: image::images/aop-proxy-plain-pojo-call.png[] -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2717,14 +2541,12 @@ image::images/aop-proxy-plain-pojo-call.png[] } } ---- -==== Things change slightly when the reference that client code has is a proxy. Consider the following diagram and code snippet: image::images/aop-proxy-call.png[] -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2743,7 +2565,6 @@ image::images/aop-proxy-call.png[] } } ---- -==== The key thing to understand here is that the client code inside the `main(..)` method of the `Main` class has a reference to the proxy. This means that method calls on that @@ -2763,7 +2584,6 @@ The next approach is absolutely horrendous, and we hesitate to point it out, precisely because it is so horrendous. You can (painful as it is to us) totally tie the logic within your class to Spring AOP, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2779,14 +2599,12 @@ your class to Spring AOP, as the following example shows: } } ---- -==== This totally couples your code to Spring AOP, and it makes the class itself aware of the fact that it is being used in an AOP context, which flies in the face of AOP. It also requires some additional configuration when the proxy is being created, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2806,7 +2624,6 @@ following example shows: } } ---- -==== Finally, it must be noted that AspectJ does not have this self-invocation issue because it is not a proxy-based AOP framework. @@ -2827,7 +2644,6 @@ You can use the `org.springframework.aop.aspectj.annotation.AspectJProxyFactory` to create a proxy for a target object that is advised by one or more @AspectJ aspects. The basic usage for this class is very simple, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2844,7 +2660,6 @@ The basic usage for this class is very simple, as the following example shows: // now get the proxy object... MyInterfaceType proxy = factory.getProxy(); ---- -==== See the {api-spring-framework}/aop/aspectj/annotation/AspectJProxyFactory.html[javadoc] for more information. @@ -2885,7 +2700,6 @@ The `@Configurable` annotation marks a class as being eligible for Spring-driven configuration. In the simplest case, you can use purely it as a marker annotation, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2898,7 +2712,6 @@ following example shows: // ... } ---- -==== When used as a marker interface in this way, Spring configures new instances of the annotated type (`Account`, in this case) by using a bean definition (typically @@ -2907,7 +2720,6 @@ prototype-scoped) with the same name as the fully-qualified type name fully-qualified name of its type, a convenient way to declare the prototype definition is to omit the `id` attribute, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2915,12 +2727,10 @@ is to omit the `id` attribute, as the following example shows: ---- -==== If you want to explicitly specify the name of the prototype bean definition to use, you can do so directly in the annotation, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2933,7 +2743,6 @@ can do so directly in the annotation, as the following example shows: // ... } ---- -==== Spring now looks for a bean definition named `account` and uses that as the definition to configure new `Account` instances. @@ -2974,13 +2783,11 @@ dependencies to be injected before the constructor bodies execute and thus be available for use in the body of the constructors, you need to define this on the `@Configurable` declaration, as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @Configurable(preConstruction=true) ---- -==== You can find more information about the language semantics of the various pointcut types in AspectJ @@ -2998,7 +2805,6 @@ a reference to the bean factory that is to be used to configure new objects). If use Java-based configuration, you can add `@EnableSpringConfigured` to any `@Configuration` class, as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3008,19 +2814,16 @@ use Java-based configuration, you can add `@EnableSpringConfigured` to any } ---- -==== If you prefer XML based configuration, the Spring <> defines a convenient `context:spring-configured` element, which you can use as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== Instances of `@Configurable` objects created before the aspect has been configured result in a message being issued to the debug log and no configuration of the @@ -3029,7 +2832,6 @@ domain objects when it is initialized by Spring. In this case, you can use the `depends-on` bean attribute to manually specify that the bean depends on the configuration aspect. The following example shows how to use the `depends-on` attribute: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3041,7 +2843,6 @@ configuration aspect. The following example shows how to use the `depends-on` at ---- -==== NOTE: Do not activate `@Configurable` processing through the bean configurer aspect unless you really mean to rely on its semantics at runtime. In particular, make sure that you do @@ -3128,7 +2929,6 @@ excerpt shows how you could write an aspect to configure all instances of object defined in the domain model by using prototype bean definitions that match the fully qualified class names: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3146,7 +2946,6 @@ fully qualified class names: } ---- -==== @@ -3165,7 +2964,6 @@ normal and include the `factory-method="aspectOf"` bean attribute. This ensures Spring obtains the aspect instance by asking AspectJ for it rather than trying to create an instance itself. The following example shows how to use the `factory-method="aspectOf"` attribute: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3176,7 +2974,7 @@ an instance itself. The following example shows how to use the `factory-method=" ---- <1> Note the `factory-method="aspectOf"` attribute -==== + Non-singleton aspects are harder to configure. However, it is possible to do so by creating prototype bean definitions and using the `@Configurable` support from @@ -3193,7 +2991,6 @@ declaration. Each `` element specifies a name pattern, and only beans names matched by at least one of the patterns are used for Spring AOP auto-proxy configuration. The following example shows how to use `` elements: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3202,7 +2999,6 @@ configuration. The following example shows how to use `` elements: ---- -==== NOTE: Do not be misled by the name of the `` element. Using it results in the creation of Spring AOP proxies. The @AspectJ style of aspect @@ -3263,7 +3059,6 @@ Specifically, you can use the `@EnableLoadTimeWeaving` annotation as an alternat The following example shows the profiling aspect, which is not fancy -- it is a time-based profiler that uses the @AspectJ-style of aspect declaration: -==== [source,java,indent=0] [subs="verbatim"] ---- @@ -3295,14 +3090,12 @@ profiler that uses the @AspectJ-style of aspect declaration: public void methodsToBeProfiled(){} } ---- -==== We also need to create an `META-INF/aop.xml` file, to inform the AspectJ weaver that we want to weave our `ProfilingAspect` into our classes. This file convention, namely the presence of a file (or files) on the Java classpath called `META-INF/aop.xml` is standard AspectJ. The following example shows the `aop.xml` file: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3321,7 +3114,6 @@ namely the presence of a file (or files) on the Java classpath called ---- -==== Now we can move on to the Spring-specific portion of the configuration. We need to configure a `LoadTimeWeaver` (explained later). This load-time @@ -3330,7 +3122,6 @@ one or more `META-INF/aop.xml` files into the classes in your application. The g thing is that it does not require a lot of configuration (there are some more options that you can specify, but these are detailed later), as can be seen in the following example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3352,13 +3143,11 @@ are some more options that you can specify, but these are detailed later), as ca **** ---- -==== Now that all the required artifacts (the aspect, the `META-INF/aop.xml` file, and the Spring configuration) are in place, we can create the following driver class with a `main(..)` method to demonstrate the LTW in action: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3380,20 +3169,17 @@ file, and the Spring configuration) are in place, we can create the following dr } } ---- -==== We have one last thing to do. The introduction to this section did say that one could switch on LTW selectively on a per-`ClassLoader` basis with Spring, and this is true. However, for this example, we use a Java agent (supplied with Spring) to switch on the LTW. We use the following command to run the `Main` class shown earlier: -==== [literal] [subs="verbatim,quotes"] ---- java -javaagent:C:/projects/foo/lib/global/spring-instrument.jar foo.Main ---- -==== The `-javaagent` is a flag for specifying and enabling http://docs.oracle.com/javase/6/docs/api/java/lang/instrument/package-summary.html[agents @@ -3408,7 +3194,6 @@ implementation so that the profiler actually captures something other than 0 milliseconds (the `01234` milliseconds is not an overhead introduced by the AOP). The following listing shows the output we got when we ran our profiler: -==== [literal] [subs="verbatim,quotes"] ---- @@ -3420,13 +3205,11 @@ ms % Task name ------ ----- ---------------------------- 01234 100% calculateEntitlement ---- -==== Since this LTW is effected by using full-blown AspectJ, we are not limited only to advising Spring beans. The following slight variation on the `Main` program yields the same result: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3448,7 +3231,6 @@ result: } } ---- -==== Notice how, in the preceding program, we bootstrap the Spring container and then create a new instance of the `StubEntitlementCalculationService` totally outside @@ -3521,7 +3303,6 @@ enough because the LTW support uses `BeanFactoryPostProcessors`.) To enable the Spring Framework's LTW support, you need to configure a `LoadTimeWeaver`, which typically is done by using the `@EnableLoadTimeWeaving` annotation, as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3531,13 +3312,11 @@ which typically is done by using the `@EnableLoadTimeWeaving` annotation, as fol } ---- -==== Alternatively, if you prefer XML-based configuration, use the `` element. Note that the element is defined in the `context` namespace. The following example shows how to use ``: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3555,7 +3334,6 @@ Alternatively, if you prefer XML-based configuration, use the ---- -==== The preceding configuration automatically defines and registers a number of LTW-specific infrastructure beans, such as a `LoadTimeWeaver` and an `AspectJWeavingEnabler`, for you. @@ -3602,7 +3380,6 @@ To specify a specific `LoadTimeWeaver` with Java configuration, implement the `LoadTimeWeavingConfigurer` interface and override the `getLoadTimeWeaver()` method. The following example specifies a `ReflectiveLoadTimeWeaver`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3616,13 +3393,11 @@ following example specifies a `ReflectiveLoadTimeWeaver`: } } ---- -==== If you use XML-based configuration, you can specify the fully qualified classname as the value of the `weaver-class` attribute on the `` element. Again, the following example specifies a `ReflectiveLoadTimeWeaver`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3641,7 +3416,6 @@ element. Again, the following example specifies a `ReflectiveLoadTimeWeaver`: ---- -==== The `LoadTimeWeaver` that is defined and registered by the configuration can be later retrieved from the Spring container by using the well known name, `loadTimeWeaver`. @@ -3706,7 +3480,6 @@ individually for each web application as follows: . Instruct Tomcat to use the custom class loader (instead of the default) by editing the web application context file, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3715,7 +3488,6 @@ individually for each web application as follows: loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/> ---- -==== Apache Tomcat 6.0+ supports several context locations: @@ -3754,13 +3526,11 @@ Note that, on JBoss 6.x, you need to disable the app server scanning to prevent loading the classes before the application actually starts. A quick workaround is to add to your artifact a file named `WEB-INF/jboss-scanning.xml` with the following content: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== [[aop-aj-ltw-environment-generic]] ===== Generic Java Applications @@ -3774,13 +3544,11 @@ requires a Spring-specific (but very general) VM agent, To use it, you must start the virtual machine with the Spring agent by supplying the following JVM options: -==== [literal] [subs="verbatim,quotes"] ---- -javaagent:/path/to/org.springframework.instrument-{version}.jar ---- -==== Note that this requires modification of the VM launch script, which may prevent you from using this in application server environments (depending on your operation policies). diff --git a/src/docs/asciidoc/core/core-appendix.adoc b/src/docs/asciidoc/core/core-appendix.adoc index f33484b984..272ad4b651 100644 --- a/src/docs/asciidoc/core/core-appendix.adoc +++ b/src/docs/asciidoc/core/core-appendix.adoc @@ -21,7 +21,6 @@ To use the tags in the `util` schema, you need to have the following preamble at of your Spring XML configuration file (the text in the snippet references the correct schema so that the tags in the `util` namespace are available to you): -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -35,7 +34,6 @@ correct schema so that the tags in the `util` namespace are available to you): ---- -==== @@ -44,7 +42,6 @@ correct schema so that the tags in the `util` namespace are available to you): Consider the following bean definition: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -55,7 +52,6 @@ Consider the following bean definition: ---- -==== The preceding configuration uses a Spring `FactoryBean` implementation (the `FieldRetrievingFactoryBean`) to set the value of the `isolation` property on a bean @@ -66,7 +62,6 @@ plumbing to the end user. The following XML Schema-based version is more concise, clearly expresses the developer's intent ("`inject this constant value`"), and it reads better: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -76,7 +71,6 @@ developer's intent ("`inject this constant value`"), and it reads better: ---- -==== @@ -92,7 +86,6 @@ The following example shows how a `static` field is exposed, by using the {api-spring-framework}/beans/factory/config/FieldRetrievingFactoryBean.html#setStaticField(java.lang.String)[`staticField`] property: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -101,26 +94,22 @@ property: ---- -==== There is also a convenience usage form where the `static` field is specified as the bean name, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== This does mean that there is no longer any choice in what the bean `id` is (so any other bean that refers to it also has to use this longer name), but this form is very concise to define and very convenient to use as an inner bean since the `id` does not have to be specified for the bean reference, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -131,7 +120,6 @@ to be specified for the bean reference, as the following example shows: ---- -==== You can also access a non-static (instance) field of another bean, as described in the API documentation for the @@ -144,7 +132,6 @@ anything about the Spring internals (or even about classes such as the `FieldRetrievingFactoryBean`). The following example enumeration shows how easy injecting an enum value is: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -156,11 +143,9 @@ enum value is: EXTENDED } ---- -==== Now consider the following setter of type `PersistenceContextType` and the corresponding bean definition: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -183,7 +168,6 @@ Now consider the following setter of type `PersistenceContextType` and the corre ---- -==== @@ -192,7 +176,6 @@ Now consider the following setter of type `PersistenceContextType` and the corre Consider the following example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -209,7 +192,6 @@ Consider the following example: ---- -==== The preceding configuration uses a Spring `FactoryBean` implementation (the `PropertyPathFactoryBean`) to create a bean (of type `int`) called `testBean.age` that @@ -217,7 +199,6 @@ has a value equal to the `age` property of the `testBean` bean. Now consider the following example, which adds a `` element: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -234,7 +215,6 @@ Now consider the following example, which adds a `` element ---- -==== The value of the `path` attribute of the `` element follows the form of `beanName.beanProperty`. In this case, it picks up the `age` property of the bean named @@ -250,7 +230,6 @@ argument. The following example shows a path being used against another bean, by name: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -271,11 +250,9 @@ The following example shows a path being used against another bean, by name: ---- -==== In the following example, a path is evaluated against an inner bean: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -290,12 +267,10 @@ In the following example, a path is evaluated against an inner bean: ---- -==== There is also a shortcut form, where the bean name is the property path. The following example shows the shortcut form: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -303,13 +278,11 @@ The following example shows the shortcut form: ---- -==== This form does mean that there is no choice in the name of the bean. Any reference to it also has to use the same `id`, which is the path. If used as an inner bean, there is no need to refer to it at all, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -320,7 +293,6 @@ bean, there is no need to refer to it at all, as the following example shows: ---- -==== You can specifically set the result type in the actual definition. This is not necessary for most use cases, but it can sometimes be useful. See the javadoc for more info on @@ -332,7 +304,6 @@ this feature. Consider the following example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -341,7 +312,6 @@ Consider the following example: ---- -==== The preceding configuration uses a Spring `FactoryBean` implementation (the `PropertiesFactoryBean`) to instantiate a `java.util.Properties` instance with values @@ -349,14 +319,12 @@ loaded from the supplied <> location). The following example uses a `util:properties` element to make a more concise representation: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== @@ -365,7 +333,6 @@ The following example uses a `util:properties` element to make a more concise re Consider the following example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -381,7 +348,6 @@ Consider the following example: ---- -==== The preceding configuration uses a Spring `FactoryBean` implementation (the `ListFactoryBean`) to create a `java.util.List` instance and initialize it with values taken @@ -389,7 +355,6 @@ from the supplied `sourceList`. The following example uses a `` element to make a more concise representation: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -401,14 +366,12 @@ The following example uses a `` element to make a more concise repre porfiry@gov.org ---- -==== You can also explicitly control the exact type of `List` that is instantiated and populated by using the `list-class` attribute on the `` element. For example, if we really need a `java.util.LinkedList` to be instantiated, we could use the following configuration: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -419,7 +382,6 @@ following configuration: d'Arcachon@nemesis.org ---- -==== If no `list-class` attribute is supplied, the container chooses a `List` implementation. @@ -430,7 +392,6 @@ If no `list-class` attribute is supplied, the container chooses a `List` impleme Consider the following example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -446,7 +407,6 @@ Consider the following example: ---- -==== The preceding configuration uses a Spring `FactoryBean` implementation (the `MapFactoryBean`) to create a `java.util.Map` instance initialized with key-value pairs @@ -454,7 +414,6 @@ taken from the supplied `'sourceMap'`. The following example uses a `` element to make a more concise representation: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -466,14 +425,12 @@ The following example uses a `` element to make a more concise repres ---- -==== You can also explicitly control the exact type of `Map` that is instantiated and populated by using the `'map-class'` attribute on the `` element. For example, if we really need a `java.util.TreeMap` to be instantiated, we could use the following configuration: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -484,7 +441,6 @@ following configuration: ---- -==== If no `'map-class'` attribute is supplied, the container chooses a `Map` implementation. @@ -495,7 +451,6 @@ If no `'map-class'` attribute is supplied, the container chooses a `Map` impleme Consider the following example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -511,7 +466,6 @@ Consider the following example: ---- -==== The preceding configuration uses a Spring `FactoryBean` implementation (the `SetFactoryBean`) to create a `java.util.Set` instance initialized with values taken @@ -519,7 +473,6 @@ from the supplied `sourceSet`. The following example uses a `` element to make a more concise representation: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -531,14 +484,12 @@ The following example uses a `` element to make a more concise repres porfiry@gov.org ---- -==== You can also explicitly control the exact type of `Set` that is instantiated and populated by using the `set-class` attribute on the `` element. For example, if we really need a `java.util.TreeSet` to be instantiated, we could use the following configuration: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -549,7 +500,6 @@ following configuration: porfiry@gov.org ---- -==== If no `set-class` attribute is supplied, the container chooses a `Set` implementation. @@ -568,7 +518,6 @@ the following preamble at the top of your Spring XML configuration file (the tex snippet references the correct schema so that the tags in the `aop` namespace are available to you): -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -582,7 +531,6 @@ are available to you): ---- -==== @@ -595,7 +543,6 @@ a lot of the "`grunt`" work in Spring, such as `BeanfactoryPostProcessors`. The snippet references the correct schema so that the elements in the `context` namespace are available to you: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -609,7 +556,6 @@ available to you: ---- -==== @@ -696,7 +642,6 @@ The following example shows the `` element in the context of a surroundin (note that, without any logic to interpret it, the metadata is effectively useless as it stands). -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -714,7 +659,7 @@ as it stands). ---- <1> This is the example `meta` element -==== + In the case of the preceding example, you could assume that there is some logic that consumes the bean definition and sets up some caching infrastructure that uses the supplied @@ -749,7 +694,6 @@ XML extension (a custom XML element) that lets us configure objects of the type `SimpleDateFormat` (from the `java.text` package). When we are done, we will be able to define bean definitions of type `SimpleDateFormat` as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -757,7 +701,6 @@ we will be able to define bean definitions of type `SimpleDateFormat` as follows pattern="yyyy-MM-dd HH:mm" lenient="true"/> ---- -==== (We include much more detailed examples follow later in this appendix. The intent of this first simple example is to walk you @@ -772,7 +715,6 @@ Creating an XML configuration extension for use with Spring's IoC container star authoring an XML Schema to describe the extension. For our example, we use the following schema to configure `SimpleDateFormat` objects: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -804,14 +746,12 @@ to configure `SimpleDateFormat` objects: (meaning they have an `id` attribute that we can use as the bean identifier in the container). We can use this attribute because we imported the Spring-provided `beans` namespace. -==== The preceding schema lets us configure `SimpleDateFormat` objects directly in an XML application context file by using the `` element, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -819,12 +759,10 @@ example shows: pattern="yyyy-MM-dd HH:mm" lenient="true"/> ---- -==== Note that, after we have created the infrastructure classes, the preceding snippet of XML is essentially the same as the following XML snippet: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -833,7 +771,6 @@ essentially the same as the following XML snippet: ---- -==== The second of the two preceding snippets creates a bean in the container (identified by the name `dateFormat` of type @@ -876,7 +813,6 @@ element results in a single `SimpleDateFormat` bean definition). Spring features number of convenience classes that support this scenario. In the following example, we use the `NamespaceHandlerSupport` class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -892,7 +828,6 @@ use the `NamespaceHandlerSupport` class: } ---- -==== You may notice that there is not actually a whole lot of parsing logic in this class. Indeed, the `NamespaceHandlerSupport` class has a built-in notion of @@ -916,7 +851,6 @@ responsible for parsing one distinct top-level XML element defined in the schema the parser, we' have access to the XML element (and thus to its subelements, too) so that we can parse our custom XML content, as you can see in the following example: -==== [source,java,indent=0] ---- package org.springframework.samples.xml; @@ -954,7 +888,7 @@ the basic grunt work of creating a single `BeanDefinition`. <2> We supply the `AbstractSingleBeanDefinitionParser` superclass with the type that our single `BeanDefinition` represents. -==== + In this simple case, this is all that we need to do. The creation of our single `BeanDefinition` is handled by the `AbstractSingleBeanDefinitionParser` superclass, as @@ -980,13 +914,11 @@ these special properties files, the formats of which are detailed in the next tw The properties file called `spring.handlers` contains a mapping of XML Schema URIs to namespace handler classes. For our example, we need to write the following: -==== [literal] [subs="verbatim,quotes"] ---- http\://www.mycompany.com/schema/myns=org.springframework.samples.xml.MyNamespaceHandler ---- -==== (The `:` character is a valid delimiter in the Java properties format, so `:` character in the URI needs to be escaped with a backslash.) @@ -1009,13 +941,11 @@ properties file, Spring searches for the schema (in this case, `myns.xsd` in the `org.springframework.samples.xml` package) on the classpath. The following snippet shows the line we need to add for our custom schema: -==== [literal] [subs="verbatim,quotes"] ---- http\://www.mycompany.com/schema/myns/myns.xsd=org/springframework/samples/xml/myns.xsd ---- -==== (Remember that the `:` character must be escaped.) @@ -1032,7 +962,6 @@ one of the "`custom`" extensions that Spring provides. The following example uses the custom `` element developed in the previous steps in a Spring XML configuration file: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1057,7 +986,6 @@ in a Spring XML configuration file: ---- <1> Our custom bean. -==== @@ -1074,7 +1002,6 @@ This section presents some more detailed examples of custom XML extensions. The example presented in this section shows how you to write the various artifacts required to satisfy a target of the following configuration: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1096,7 +1023,6 @@ to satisfy a target of the following configuration: ---- -==== The preceding configuration nests custom extensions within each other. The class that is actually configured by the `` element is the `Component` @@ -1105,7 +1031,6 @@ setter method for the `components` property. This makes it hard (or rather impos to configure a bean definition for the `Component` class by using setter injection. The following listing shows the `Component` class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1138,12 +1063,11 @@ The following listing shows the `Component` class: } ---- -==== The typical solution to this issue is to create a custom `FactoryBean` that exposes a setter property for the `components` property. The following listing shows such a custom `FactoryBean`: -==== + [source,java,indent=0] [subs="verbatim,quotes"] @@ -1186,7 +1110,6 @@ setter property for the `components` property. The following listing shows such } ---- -==== This works nicely, but it exposes a lot of Spring plumbing to the end user. What we are going to do is write a custom extension that hides away all of @@ -1194,7 +1117,6 @@ this Spring plumbing. If we stick to <>, we start off by creating the XSD schema to define the structure of our custom tag, as the following listing shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1218,11 +1140,9 @@ custom tag, as the following listing shows: ---- -==== Again following <>, we then create a custom `NamespaceHandler`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1238,13 +1158,11 @@ Again following <>, we th } ---- -==== Next up is the custom `BeanDefinitionParser`. Remember that we are creating `BeanDefinition` that describes a `ComponentFactoryBean`. The following listing shows our custom `BeanDefinitionParser`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1295,12 +1213,10 @@ custom `BeanDefinitionParser`: } ---- -==== Finally, the various artifacts need to be registered with the Spring XML infrastructure, by modifying the `META-INF/spring.handlers` and `META-INF/spring.schemas` files, as follows: -==== [literal] [subs="verbatim,quotes"] ---- @@ -1314,7 +1230,6 @@ http\://www.foo.com/schema/component=com.foo.ComponentNamespaceHandler # in 'META-INF/spring.schemas' http\://www.foo.com/schema/component/component.xsd=com/foo/component.xsd ---- -==== @@ -1333,7 +1248,6 @@ http://jcp.org/en/jsr/detail?id=107[JCache], and you want to ensure that the nam JCache instance is eagerly started within the surrounding cluster. The following listing shows such a definition: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1342,7 +1256,6 @@ listing shows such a definition: ---- -==== We can then create another `BeanDefinition` when the `'jcache:cache-name'` attribute is parsed. This `BeanDefinition` then initializes @@ -1350,7 +1263,6 @@ the named JCache for us. We can also modify the existing `BeanDefinition` for th `'checkingAccountService'` so that it has a dependency on this new JCache-initializing `BeanDefinition`. The following listing shows our `JCacheInitializer`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1370,12 +1282,10 @@ JCache-initializing `BeanDefinition`. The following listing shows our `JCacheIni } ---- -==== Now we can move onto the custom extension. First, we need to author the XSD schema that describes the custom attribute, as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1390,11 +1300,9 @@ custom attribute, as follows: ---- -==== Next, we need to create the associated `NamespaceHandler`, as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1411,13 +1319,11 @@ Next, we need to create the associated `NamespaceHandler`, as follows: } ---- -==== Next, we need to create the parser. Note that, in this case, because we are going to parse an XML attribute, we write a `BeanDefinitionDecorator` rather than a `BeanDefinitionParser`. The following listing shows our `BeanDefinitionDecorator`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1473,12 +1379,10 @@ The following listing shows our `BeanDefinitionDecorator`: } ---- -==== Finally, we need to register the various artifacts with the Spring XML infrastructure by modifying the `META-INF/spring.handlers` and `META-INF/spring.schemas` files, as follows: -==== [literal] [subs="verbatim,quotes"] ---- @@ -1492,4 +1396,3 @@ http\://www.foo.com/schema/jcache=com.foo.JCacheNamespaceHandler # in 'META-INF/spring.schemas' http\://www.foo.com/schema/jcache/jcache.xsd=com/foo/jcache.xsd ---- -==== diff --git a/src/docs/asciidoc/core/core-beans.adoc b/src/docs/asciidoc/core/core-beans.adoc index 4d3495ceab..4d755486c7 100644 --- a/src/docs/asciidoc/core/core-beans.adoc +++ b/src/docs/asciidoc/core/core-beans.adoc @@ -136,7 +136,6 @@ dependency-inject domain objects with Spring>>. The following example shows the basic structure of XML-based configuration metadata: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -163,7 +162,7 @@ The following example shows the basic structure of XML-based configuration metad <2> The `class` attribute defines the type of the bean and uses the fully qualified classname. -==== + The value of the `id` attribute refers to collaborating objects. The XML for referring to collaborating objects is not shown in this example. See @@ -179,13 +178,11 @@ supplied to an `ApplicationContext` constructor are resource strings that let the container load configuration metadata from a variety of external resources, such as the local file system, the Java `CLASSPATH`, and so on. -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml"); ---- -==== [NOTE] ==== @@ -197,7 +194,6 @@ mechanism for reading an InputStream from locations defined in a URI syntax. In The following example shows the service layer objects `(services.xml)` configuration file: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -219,11 +215,9 @@ The following example shows the service layer objects `(services.xml)` configura ---- -==== The following example shows the data access objects `daos.xml` file: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -246,7 +240,6 @@ The following example shows the data access objects `daos.xml` file: ---- -==== In the preceding example, the service layer consists of the `PetStoreServiceImpl` class and two data access objects of the types `JpaAccountDao` and `JpaItemDao` (based @@ -269,7 +262,6 @@ XML fragments. This constructor takes multiple `Resource` locations, as was show occurrences of the `` element to load bean definitions from another file or files. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -282,7 +274,6 @@ files. The following example shows how to do so: ---- -==== In the preceding example, external bean definitions are loaded from three files: `services.xml`, `messageSource.xml`, and `themeSource.xml`. All location paths are @@ -324,7 +315,6 @@ be expressed in Spring's Groovy Bean Definition DSL, as known from the Grails fr Typically, such configuration live in a ".groovy" file with the structure shown in the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -346,7 +336,6 @@ following example: } } ---- -==== This configuration style is largely equivalent to XML bean definitions and even supports Spring's XML configuration namespaces. It also allows for importing XML @@ -364,7 +353,6 @@ name, Class requiredType)`, you can retrieve instances of your beans. The `ApplicationContext` lets you read bean definitions and access them, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -377,7 +365,6 @@ example shows: // use configured instance List userList = service.getUsernameList(); ---- -==== With Groovy configuration, bootstrapping looks very similar. It has a different context implementation class which is Groovy-aware (but also understands XML bean definitions). @@ -393,7 +380,6 @@ The most flexible variant is `GenericApplicationContext` in combination with rea delegates -- for example, with `XmlBeanDefinitionReader` for XML files, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -401,12 +387,10 @@ example shows: new XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml"); context.refresh(); ---- -==== You can also use the `GroovyBeanDefinitionReader` for Groovy files, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -414,7 +398,6 @@ example shows: new GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy"); context.refresh(); ---- -==== You can mix and match such reader delegates on the same `ApplicationContext`, reading bean definitions from diverse configuration sources. @@ -569,13 +552,11 @@ amongst each subsystem, with each subsystem having its own set of object definit In XML-based configuration metadata, you can use the `` element to accomplish this. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== In this case, a bean (in the same container) named `fromName` may also, after the use of this alias definition, be referred to as `toName`. @@ -587,14 +568,12 @@ that uses both these subsystems, the main application refers to the DataSource b name of `myApp-dataSource`. To have all three names refer to the same object, you can add the following alias definitions to the configuration metadata: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== Now each component and the main application can refer to the dataSource through a name that is unique and guaranteed not to clash with any other definition (effectively @@ -664,7 +643,6 @@ well. With XML-based configuration metadata you can specify your bean class as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -672,7 +650,6 @@ With XML-based configuration metadata you can specify your bean class as follows ---- -==== For details about the mechanism for supplying arguments to the constructor (if required) and setting object instance properties after the object is constructed, see @@ -694,7 +671,6 @@ factory method. The definition does not specify the type (class) of the returned only the class containing the factory method. In this example, the `createInstance()` method must be a static method. The following example shows how to specify a factory method: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -702,11 +678,9 @@ method must be a static method. The following example shows how to specify a fac class="examples.ClientService" factory-method="createInstance"/> ---- -==== The following example shows a class that would work with the preceding bean definition: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -719,7 +693,6 @@ The following example shows a class that would work with the preceding bean defi } } ---- -==== For details about the mechanism for supplying (optional) arguments to the factory method and setting object instance properties after the object is returned from the factory, @@ -738,7 +711,6 @@ the instance method that is to be invoked to create the object. Set the name of factory method itself with the `factory-method` attribute. The following example shows how to configure such a bean: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -752,11 +724,9 @@ how to configure such a bean: factory-bean="serviceLocator" factory-method="createClientServiceInstance"/> ---- -==== The following example shows the corresponding Java class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -769,11 +739,9 @@ The following example shows the corresponding Java class: } } ---- -==== One factory class can also hold more than one factory method, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -789,11 +757,9 @@ One factory class can also hold more than one factory method, as the following e factory-bean="serviceLocator" factory-method="createAccountServiceInstance"/> ---- -==== The following example shows the corresponding Java class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -812,7 +778,6 @@ The following example shows the corresponding Java class: } } ---- -==== This approach shows that the factory bean itself can be managed and configured through dependency injection (DI). See <` element. -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -937,14 +897,12 @@ element. ---- -==== When another bean is referenced, the type is known, and matching can occur (as was the case with the preceding example). When a simple type is used, such as `true`, Spring cannot determine the type of the value, and so cannot match by type without help. Consider the following class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -964,7 +922,6 @@ by type without help. Consider the following class: } } ---- -==== .[[beans-factory-ctor-arguments-type]]Constructor argument type matching -- @@ -972,7 +929,6 @@ In the preceding scenario, the container can use type matching with simple types you explicitly specify the type of the constructor argument by using the `type` attribute. as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -981,7 +937,6 @@ as the following example shows: ---- -==== -- .[[beans-factory-ctor-arguments-index]]Constructor argument index @@ -989,7 +944,6 @@ as the following example shows: You can use the `index` attribute to specify explicitly the index of constructor arguments, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -998,7 +952,6 @@ as the following example shows: ---- -==== In addition to resolving the ambiguity of multiple simple values, specifying an index resolves ambiguity where a constructor has two arguments of the same type. @@ -1011,7 +964,6 @@ NOTE: The index is 0-based. You can also use the constructor parameter name for value disambiguation, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1020,7 +972,6 @@ example shows: ---- -==== Keep in mind that, to make this work out of the box, your code must be compiled with the debug flag enabled so that Spring can look up the parameter name from the constructor. @@ -1029,7 +980,6 @@ http://download.oracle.com/javase/6/docs/api/java/beans/ConstructorProperties.ht JDK annotation to explicitly name your constructor arguments. The sample class would then have to look as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1046,7 +996,6 @@ then have to look as follows: } } ---- -==== -- @@ -1061,7 +1010,6 @@ The following example shows a class that can only be dependency-injected by usin setter injection. This class is conventional Java. It is a POJO that has no dependencies on container specific interfaces, base classes, or annotations. -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1078,7 +1026,6 @@ on container specific interfaces, base classes, or annotations. // business logic that actually uses the injected MovieFinder is omitted... } ---- -==== The `ApplicationContext` supports constructor-based and setter-based DI for the beans it manages. It also supports setter-based DI after some dependencies have already been @@ -1199,7 +1146,6 @@ are invoked. The following example uses XML-based configuration metadata for setter-based DI. A small part of a Spring XML configuration file specifies some bean definitions as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1217,11 +1163,9 @@ part of a Spring XML configuration file specifies some bean definitions as follo ---- -==== The following example shows the corresponding `ExampleBean` class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1246,12 +1190,10 @@ The following example shows the corresponding `ExampleBean` class: } } ---- -==== In the preceding example, setters are declared to match against the properties specified in the XML file. The following example uses constructor-based DI: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1270,11 +1212,9 @@ in the XML file. The following example uses constructor-based DI: ---- -==== The following example shows the corresponding `ExampleBean` class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1294,7 +1234,6 @@ The following example shows the corresponding `ExampleBean` class: } } ---- -==== The constructor arguments specified in the bean definition are used as arguments to the constructor of the `ExampleBean`. @@ -1302,7 +1241,6 @@ the constructor of the `ExampleBean`. Now consider a variant of this example, where, instead of using a constructor, Spring is told to call a `static` factory method to return an instance of the object: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1315,11 +1253,9 @@ told to call a `static` factory method to return an instance of the object: ---- -==== The following example shows the corresponding `ExampleBean` class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1342,7 +1278,6 @@ The following example shows the corresponding `ExampleBean` class: } } ---- -==== Arguments to the `static` factory method are supplied by `` elements, exactly the same as if a constructor had actually been used. The type of the class being @@ -1373,7 +1308,6 @@ argument as a human-readable string representation. Spring's values from a `String` to the actual type of the property or argument. The following example shows various values being set: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1385,12 +1319,10 @@ The following example shows various values being set: ---- -==== The following example uses the <> for even more succinct XML configuration: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1409,7 +1341,6 @@ XML configuration: ---- -==== The preceding XML is more succinct. However, typos are discovered at runtime rather than design time, unless you use an IDE (such as http://www.jetbrains.com/idea/[IntelliJ @@ -1419,7 +1350,6 @@ assistance is highly recommended. You can also configure a `java.util.Properties` instance, as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1435,7 +1365,6 @@ You can also configure a `java.util.Properties` instance, as follows: ---- -==== The Spring container converts the text inside the `` element into a `java.util.Properties` instance by using the JavaBeans `PropertyEditor` mechanism. This @@ -1449,7 +1378,6 @@ The `idref` element is simply an error-proof way to pass the `id` (a string valu a reference) of another bean in the container to a `` or `` element. The following example shows how to use it: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1461,12 +1389,10 @@ element. The following example shows how to use it: ---- -==== The preceding bean definition snippet is exactly equivalent (at runtime) to the following snippet: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1476,7 +1402,6 @@ following snippet: ---- -==== The first form is preferable to the second, because using the `idref` tag lets the container validate at deployment time that the referenced, named bean actually @@ -1515,13 +1440,11 @@ parent container, regardless of whether it is in the same XML file. The value of as one of the values in the `name` attribute of the target bean. The following example shows how to use a `ref` element: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== Specifying the target bean through the `parent` attribute creates a reference to a bean that is in a parent container of the current container. The value of the `parent` @@ -1532,7 +1455,6 @@ when you have a hierarchy of containers and you want to wrap an existing bean in container with a proxy that has the same name as the parent bean. The following pair of listings shows how to use the `parent` attribute: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1554,7 +1476,6 @@ listings shows how to use the `parent` attribute: ---- -==== NOTE: The `local` attribute on the `ref` element is no longer supported in the 4.0 beans XSD, since it does not provide value over a regular `bean` reference any more. Change @@ -1567,7 +1488,6 @@ your existing `ref local` references to `ref bean` when upgrading to the 4.0 sch A `` element inside the `` or `` elements defines an inner bean, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1581,7 +1501,6 @@ inner bean, as the following example shows: ---- -==== An inner bean definition does not require a defined ID or name. If specified, the container does not use such a value as an identifier. The container also ignores the `scope` flag on @@ -1603,7 +1522,6 @@ The ``, ``, ``, and `` elements set the properties and arguments of the Java `Collection` types `List`, `Set`, `Map`, and `Properties`, respectively. The following example shows how to use them: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1639,18 +1557,15 @@ respectively. The following example shows how to use them: ---- -==== The value of a map key or value, or a set value, can also be any of the following elements: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- bean | ref | idref | list | set | map | props | value | null ---- -==== [[beans-collection-elements-merging]] ===== Collection Merging @@ -1668,7 +1583,6 @@ with parent and child bean definitions may wish to read the The following example demonstrates collection merging: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1692,7 +1606,6 @@ The following example demonstrates collection merging: ---- -==== Notice the use of the `merge=true` attribute on the `` element of the `adminEmails` property of the `child` bean definition. When the `child` bean is resolved @@ -1701,7 +1614,6 @@ and instantiated by the container, the resulting instance has an `adminEmails` `adminEmails` collection with the parent's `adminEmails` collection. The following listing shows the result: -==== [literal] [subs="verbatim,quotes"] ---- @@ -1709,7 +1621,6 @@ administrator=administrator@example.com sales=sales@example.com support=support@example.co.uk ---- -==== The child `Properties` collection's value set inherits all property elements from the parent ``, and the child's value for the `support` value overrides the value in @@ -1743,7 +1654,6 @@ type-conversion support such that the elements of your strongly-typed `Collectio instances are converted to the appropriate type prior to being added to the `Collection`. The following Java class and bean definition show how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1772,7 +1682,6 @@ The following Java class and bean definition show how to do so: ---- -==== When the `accounts` property of the `something` bean is prepared for injection, the generics information about the element type of the strongly-typed `Map` is @@ -1788,7 +1697,6 @@ Spring treats empty arguments for properties and the like as empty `Strings`. Th following XML-based configuration metadata snippet sets the `email` property to the empty `String` value (""). -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1796,21 +1704,17 @@ following XML-based configuration metadata snippet sets the `email` property to ---- -==== The preceding example is equivalent to the following Java code: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- exampleBean.setEmail(""); ---- -==== The `` element handles `null` values. The following listing shows an example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1820,17 +1724,14 @@ The `` element handles `null` values. The following listing shows an exam ---- -==== The preceding configuration is equivalent to the following Java code: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- exampleBean.setEmail(null); ---- -==== [[beans-p-namespace]] @@ -1847,7 +1748,6 @@ in an XSD file and exists only in the core of Spring. The following example shows two XML snippets (the first uses standard XML format and the second uses the p-namespace) that resolve to the same result: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1865,7 +1765,6 @@ standard XML format and the second uses the p-namespace) that resolve to the sam p:email="someone@somewhere.com"/> ---- -==== The example shows an attribute in the p-namespace called `email` in the bean definition. This tells Spring to include a property declaration. As previously mentioned, the @@ -1875,7 +1774,6 @@ to the property name. This next example includes two more bean definitions that both have a reference to another bean: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1900,7 +1798,6 @@ another bean: ---- -==== This example includes not only a property value using the p-namespace but also uses a special format to declare property references. Whereas the first bean @@ -1927,7 +1824,6 @@ then nested `constructor-arg` elements. The following example uses the `c:` namespace to do the same thing as the from <>: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1953,7 +1849,6 @@ The following example uses the `c:` namespace to do the same thing as the from ---- -==== The `c:` namespace uses the same conventions as the `p:` one (a trailing `-ref` for bean references) for setting the constructor arguments by their names. Similarly, @@ -1964,7 +1859,6 @@ For the rare cases where the constructor argument names are not available (usual the bytecode was compiled without debugging information), you can use fallback to the argument indexes, as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1972,7 +1866,6 @@ argument indexes, as follows: ---- -==== NOTE: Due to the XML grammar, the index notation requires the presence of the leading `_`, as XML attribute names cannot start with a number (even though some IDEs allow it). @@ -1992,7 +1885,6 @@ You can use compound or nested property names when you set bean properties, as l all components of the path except the final property name are not `null`. Consider the following bean definition: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2000,7 +1892,6 @@ following bean definition: ---- -==== The `something` bean has a `fred` property, which has a `bob` property, which has a `sammy` property, and that final `sammy` property is being set to a value of `123`. In order for @@ -2021,20 +1912,17 @@ explicitly force one or more beans to be initialized before the bean using this is initialized. The following example uses the `depends-on` attribute to express a dependency on a single bean: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== To express a dependency on multiple beans, supply a list of bean names as the value of the `depends-on` attribute (commas, whitespace, and semicolons are valid delimiters): -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2045,7 +1933,6 @@ delimiters): ---- -==== NOTE: The `depends-on` attribute can specify both an initialization-time dependency and, in the case of <> beans only, a corresponding @@ -2070,14 +1957,12 @@ instance when it is first requested, rather than at startup. In XML, this behavior is controlled by the `lazy-init` attribute on the `` element, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== When the preceding configuration is consumed by an `ApplicationContext`, the `lazy` bean is not eagerly pre-instantiated when the `ApplicationContext` starts, @@ -2091,7 +1976,6 @@ is injected into a singleton bean elsewhere that is not lazy-initialized. You can also control lazy-initialization at the container level by using the `default-lazy-init` attribute on the `` element, a the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2099,7 +1983,6 @@ You can also control lazy-initialization at the container level by using the ---- -==== @@ -2249,7 +2132,6 @@ and by <> as typically new) bean B instance every time bean A needs it. The following example shows this approach: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2284,7 +2166,6 @@ shows this approach: } } ---- -==== The preceding is not desirable, because the business code is aware of and coupled to the Spring Framework. Method Injection, a somewhat advanced feature of the Spring IoC @@ -2326,7 +2207,6 @@ Spring container dynamically overrides the implementation of the `createCommand( method. The `CommandManager` class does not have any Spring dependencies, as the reworked example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2348,24 +2228,20 @@ the reworked example shows: protected abstract Command createCommand(); } ---- -==== In the client class that contains the method to be injected (the `CommandManager` in this case), the method to be injected requires a signature of the following form: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- [abstract] theMethodName(no-arguments); ---- -==== If the method is `abstract`, the dynamically-generated subclass implements the method. Otherwise, the dynamically-generated subclass overrides the concrete method defined in the original class. Consider the following example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2379,7 +2255,6 @@ the original class. Consider the following example: ---- -==== The bean identified as `commandManager` calls its own `createCommand()` method whenever it needs a new instance of the `myCommand` bean. You must be careful to deploy @@ -2390,7 +2265,6 @@ bean is returned each time. Alternatively, within the annotation-based component model, you can declare a lookup method through the `@Lookup` annotation, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2406,12 +2280,10 @@ method through the `@Lookup` annotation, as the following example shows: protected abstract Command createCommand(); } ---- -==== Or, more idiomatically, you can rely on the target bean getting resolved against the declared return type of the lookup method: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2427,7 +2299,6 @@ declared return type of the lookup method: protected abstract MyCommand createCommand(); } ---- -==== Note that you should typically declare such annotated lookup methods with a concrete stub implementation, in order for them to be compatible with Spring's component @@ -2456,7 +2327,6 @@ With XML-based configuration metadata, you can use the `replaced-method` element replace an existing method implementation with another, for a deployed bean. Consider the following class, which has a method called `computeValue` that we want to override: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2469,12 +2339,10 @@ the following class, which has a method called `computeValue` that we want to ov // some other methods... } ---- -==== A class that implements the `org.springframework.beans.factory.support.MethodReplacer` interface provides the new method definition, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2492,12 +2360,10 @@ interface provides the new method definition, as the following example shows: } } ---- -==== The bean definition to deploy the original class and specify the method override would resemble the following example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2510,7 +2376,6 @@ resemble the following example: ---- -==== You can use one or more `` elements within the `` element to indicate the method signature of the method being overridden. The signature @@ -2519,7 +2384,6 @@ exist within the class. For convenience, the type string for an argument may be substring of the fully qualified type name. For example, the following all match `java.lang.String`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2527,7 +2391,6 @@ substring of the fully qualified type name. For example, the following all match String Str ---- -==== Because the number of arguments is often enough to distinguish between each possible choice, this shortcut can save a lot of typing, by letting you type only the @@ -2619,7 +2482,6 @@ of the class defined by that bean definition. The singleton scope is the default in Spring. To define a bean as a singleton in XML, you can define a bean as shown in the following example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2628,7 +2490,6 @@ following example: ---- -==== @@ -2652,13 +2513,11 @@ singleton diagram.) The following example defines a bean as a prototype in XML: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== In contrast to the other scopes, Spring does not manage the complete lifecycle of a prototype bean. The container instantiates, configures, and otherwise assembles a @@ -2728,7 +2587,6 @@ For Servlet 3.0+, this can be done programmatically by using the `WebApplication interface. Alternatively, or for older containers, add the following declaration to your web application's `web.xml` file: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2742,14 +2600,12 @@ your web application's `web.xml` file: ... ---- -==== Alternatively, if there are issues with your listener setup, consider using Spring's `RequestContextFilter`. The filter mapping depends on the surrounding web application configuration, so you have to change it as appropriate. The following listing shows the filter part of a web application: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2766,7 +2622,6 @@ shows the filter part of a web application: ... ---- -==== `DispatcherServlet`, `RequestContextListener`, and `RequestContextFilter` all do exactly the same thing, namely bind the HTTP request object to the `Thread` that is servicing @@ -2780,13 +2635,11 @@ down the call chain. Consider the following XML configuration for a bean definition: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== The Spring container creates a new instance of the `LoginAction` bean by using the `loginAction` bean definition for each and every HTTP request. That is, the @@ -2800,7 +2653,6 @@ When using annotation-driven components or Java configuration, the `@RequestScop can be used to assign a component to the `request` scope. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2810,7 +2662,6 @@ to do so: // ... } ---- -==== @@ -2819,13 +2670,11 @@ to do so: Consider the following XML configuration for a bean definition: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== The Spring container creates a new instance of the `UserPreferences` bean by using the `userPreferences` bean definition for the lifetime of a single HTTP `Session`. In other @@ -2840,7 +2689,6 @@ HTTP `Session` is eventually discarded, the bean that is scoped to that particul When using annotation-driven components or Java configuration, you can use the `@SessionScope` annotation to assign a component to the `session` scope. -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2850,7 +2698,6 @@ When using annotation-driven components or Java configuration, you can use the // ... } ---- -==== @@ -2859,13 +2706,11 @@ When using annotation-driven components or Java configuration, you can use the Consider the following XML configuration for a bean definition: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== The Spring container creates a new instance of the `AppPreferences` bean by using the `appPreferences` bean definition once for the entire web application. That is, the @@ -2879,7 +2724,6 @@ When using annotation-driven components or Java configuration, you can use the `@ApplicationScope` annotation to assign a component to the `application` scope. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2889,7 +2733,6 @@ following example shows how to do so: // ... } ---- -==== @@ -2931,7 +2774,6 @@ See <> for more details on JSR-330 overall. The configuration in the following example is only one line, but it is important to understand the "`why`" as well as the "`how`" behind it: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2958,7 +2800,7 @@ understand the "`why`" as well as the "`how`" behind it: ---- <1> The line that defines the proxy. -==== + To create such a proxy, you insert a child `` element into a scoped bean definition (see <> and @@ -2969,7 +2811,6 @@ Consider the following singleton bean definition and contrast it with what you need to define for the aforementioned scopes (note that the following `userPreferences` bean definition as it stands is incomplete): -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2979,7 +2820,6 @@ what you need to define for the aforementioned scopes (note that the following ---- -==== In the preceding example, the singleton bean (`userManager`) is injected with a reference to the HTTP `Session`-scoped bean (`userPreferences`). The salient point here is that the @@ -3007,7 +2847,6 @@ Thus, you need the following (correct and complete) configuration when injecting `request-` and `session-scoped` beans into collaborating objects, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3019,7 +2858,6 @@ shows: ---- -==== [[beans-factory-scopes-other-injection-proxies]] ===== Choosing the Type of Proxy to Create @@ -3042,7 +2880,6 @@ the scoped bean must implement at least one interface and that all collaborators into which the scoped bean is injected must reference the bean through one of its interfaces. The following example shows a proxy based on an interface: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3055,7 +2892,6 @@ interfaces. The following example shows a proxy based on an interface: ---- -==== For more detailed information about choosing class-based or interface-based proxying, see <>. @@ -3088,50 +2924,42 @@ implementation, for example, returns the session-scoped bean (if it does not exi the method returns a new instance of the bean, after having bound it to the session for future reference). The following method returns the object from the underlying scope: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- Object get(String name, ObjectFactory objectFactory) ---- -==== The session scope implementation, for example, removes the session-scoped bean from the underlying session. The object should be returned, but you can return null if the object with the specified name is not found. The following method removes the object from the underlying scope: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- Object remove(String name) ---- -==== The following method registers the callbacks the scope should execute when it is destroyed or when the specified object in the scope is destroyed: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- void registerDestructionCallback(String name, Runnable destructionCallback) ---- -==== See the {api-spring-framework}/beans/factory/config/Scope.html#registerDestructionCallback[javadoc] or a Spring scope implementation for more information on destruction callbacks. The following method obtains the conversation identifier for the underlying scope: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- String getConversationId() ---- -==== This identifier is different for each scope. For a session scoped implementation, this identifier can be the session identifier. @@ -3145,13 +2973,11 @@ After you write and test one or more custom `Scope` implementations, you need to the Spring container aware of your new scopes. The following method is the central method to register a new `Scope` with the Spring container: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- void registerScope(String scopeName, Scope scope); ---- -==== This method is declared on the `ConfigurableBeanFactory` interface, which is available through the `BeanFactory` property on most of the concrete `ApplicationContext` @@ -3169,31 +2995,26 @@ NOTE: The next example uses `SimpleThreadScope`, which is included with Spring b registered by default. The instructions would be the same for your own custom `Scope` implementations. -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- Scope threadScope = new SimpleThreadScope(); beanFactory.registerScope("thread", threadScope); ---- -==== You can then create bean definitions that adhere to the scoping rules of your custom `Scope`, as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== With a custom `Scope` implementation, you are not limited to programmatic registration of the scope. You can also do the `Scope` registration declaratively, by using the `CustomScopeConfigurer` class, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3227,7 +3048,6 @@ of the scope. You can also do the `Scope` registration declaratively, by using t ---- -==== NOTE: When you place `` in a `FactoryBean` implementation, it is the factory bean itself that is scoped, not the object returned from `getObject()`. @@ -3287,13 +3107,11 @@ The `org.springframework.beans.factory.InitializingBean` interface lets a bean perform initialization work after the container has set all necessary properties on the bean. The `InitializingBean` interface specifies a single method: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- void afterPropertiesSet() throws Exception; ---- -==== We recommend that you do not use the `InitializingBean` interface, because it unnecessarily couples the code to Spring. Alternatively, we suggest using @@ -3303,7 +3121,6 @@ you can use the `init-method` attribute to specify the name of the method that h no-argument signature. With Java configuration, you can use the `initMethod` attribute of `@Bean`. See <>. Consider the following example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3320,12 +3137,10 @@ no-argument signature. With Java configuration, you can use the `initMethod` att } } ---- -==== The preceding example has almost exactly the same effect as the following example (which consists of two listings): -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3342,7 +3157,6 @@ consists of two listings): } } ---- -==== However, the first of the two preceding examples does not couple the code to Spring. @@ -3354,13 +3168,11 @@ Implementing the `org.springframework.beans.factory.DisposableBean` interface le bean get a callback when the container that contains it is destroyed. The `DisposableBean` interface specifies a single method: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- void destroy() throws Exception; ---- -==== We recommend that you do not use the `DisposableBean` callback interface, because it unnecessarily couples the code to Spring. Alternatively, we suggest using @@ -3370,7 +3182,6 @@ configuration metadata, you can use the `destroy-method` attribute on the `>. Consider the following definition: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3387,11 +3198,9 @@ With Java configuration, you can use the `destroyMethod` attribute of `@Bean`. S } } ---- -==== The preceding definition has almost exactly the same effect as the following definition: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3408,7 +3217,6 @@ The preceding definition has almost exactly the same effect as the following def } } ---- -==== However, the first of the two preceding definitions does not couple the code to Spring. @@ -3443,7 +3251,6 @@ Suppose that your initialization callback methods are named `init()` and your de callback methods are named `destroy()`. Your class then resembles the class in the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3463,11 +3270,9 @@ following example: } } ---- -==== You could then use that class in a bean resembling the following: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3479,7 +3284,6 @@ You could then use that class in a bean resembling the following: ---- -==== The presence of the `default-init-method` attribute on the top-level `` element attribute causes the Spring IoC container to recognize a method called `init` on the bean @@ -3546,7 +3350,6 @@ Destroy methods are called in the same order: The `Lifecycle` interface defines the essential methods for any object that has its own lifecycle requirements (such as starting and stopping some background process): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3559,7 +3362,6 @@ lifecycle requirements (such as starting and stopping some background process): boolean isRunning(); } ---- -==== Any Spring-managed object may implement the `Lifecycle` interface. Then, when the `ApplicationContext` itself receives start and stop signals (for example, for a stop/restart @@ -3567,7 +3369,6 @@ scenario at runtime), it cascades those calls to all `Lifecycle` implementations defined within that context. It does this by delegating to a `LifecycleProcessor`, shown in the following listing: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3578,7 +3379,6 @@ in the following listing: void onClose(); } ---- -==== Notice that the `LifecycleProcessor` is itself an extension of the `Lifecycle` interface. It also adds two other methods for reacting to the context being refreshed @@ -3605,7 +3405,6 @@ prior to objects of another type. In those cases, the `SmartLifecycle` interface another option, namely the `getPhase()` method as defined on its super-interface, `Phased`. The following listing shows the definition of the `Phased` interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3614,11 +3413,9 @@ another option, namely the `getPhase()` method as defined on its super-interface int getPhase(); } ---- -==== The following listing shows the definition of the `SmartLifecycle` interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3629,7 +3426,6 @@ The following listing shows the definition of the `SmartLifecycle` interface: void stop(Runnable callback); } ---- -==== When starting, the objects with the lowest phase start first. When stopping, the reverse order is followed. Therefore, an object that implements `SmartLifecycle` and @@ -3652,7 +3448,6 @@ You can override the default lifecycle processor instance by defining a bean nam `lifecycleProcessor` within the context. If you want only to modify the timeout, defining the following would suffice: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3661,7 +3456,6 @@ defining the following would suffice: ---- -==== As mentioned earlier, the `LifecycleProcessor` interface defines callback methods for the refreshing and closing of the context as well. The latter drives the shutdown @@ -3697,7 +3491,6 @@ and implement these destroy callbacks correctly. To register a shutdown hook, call the `registerShutdownHook()` method that is declared on the `ConfigurableApplicationContext` interface, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3718,7 +3511,6 @@ declared on the `ConfigurableApplicationContext` interface, as the following exa } } ---- -==== @@ -3730,7 +3522,6 @@ When an `ApplicationContext` creates an object instance that implements the with a reference to that `ApplicationContext`. The following listing shows the definition of the `ApplicationContextAware` interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3739,7 +3530,6 @@ of the `ApplicationContextAware` interface: void setApplicationContext(ApplicationContext applicationContext) throws BeansException; } ---- -==== Thus, beans can programmatically manipulate the `ApplicationContext` that created them, through the `ApplicationContext` interface or by casting the reference to a known @@ -3768,7 +3558,6 @@ When an `ApplicationContext` creates a class that implements the a reference to the name defined in its associated object definition. The following listing shows the definition of the BeanNameAware interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3777,7 +3566,6 @@ shows the definition of the BeanNameAware interface: void setBeanName(String name) throws BeansException; } ---- -==== The callback is invoked after population of normal bean properties but before an initialization callback such as `InitializingBean`, `afterPropertiesSet`, or a custom @@ -3876,7 +3664,6 @@ metadata, you can indicate a child bean definition by using the `parent` attribu specifying the parent bean as the value of this attribute. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3894,7 +3681,7 @@ to do so: ---- <1> Note the `parent` attribute. -==== + A child bean definition uses the bean class from the parent definition if none is specified but can also override it. In the latter case, the child bean class must be @@ -3913,7 +3700,6 @@ the `abstract` attribute. If the parent definition does not specify a class, exp marking the parent bean definition as `abstract` is required, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3928,7 +3714,6 @@ shows: ---- -==== The parent bean cannot be instantiated on its own because it is incomplete, and it is also explicitly marked as `abstract`. When a definition is `abstract`, it is @@ -4070,7 +3855,6 @@ it is created by the container and prints the resulting string to the system con The following listing shows the custom `BeanPostProcessor` implementation class definition: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4091,11 +3875,9 @@ The following listing shows the custom `BeanPostProcessor` implementation class } } ---- -==== The following `beans` element uses the `InstantiationTracingBeanPostProcessor`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4121,7 +3903,6 @@ The following `beans` element uses the `InstantiationTracingBeanPostProcessor`: ---- -==== Notice how the `InstantiationTracingBeanPostProcessor` is merely defined. It does not even have a name, and, because it is a bean, it can be dependency-injected as you would any @@ -4131,7 +3912,6 @@ script. The Spring dynamic language support is detailed in the chapter entitled The following Java application runs the preceding code and configuration: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4149,18 +3929,15 @@ The following Java application runs the preceding code and configuration: } ---- -==== The output of the preceding application resembles the following: -==== [literal] [subs="verbatim,quotes"] ---- Bean 'messenger' created : org.springframework.scripting.groovy.GroovyMessenger@272961 org.springframework.scripting.groovy.GroovyMessenger@272961 ---- -==== [[beans-factory-extension-bpp-examples-rabpp]] @@ -4242,7 +4019,6 @@ main XML definition file or files for the container. Consider the following XML-based configuration metadata fragment, where a `DataSource` with placeholder values is defined: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4258,7 +4034,6 @@ with placeholder values is defined: ---- -==== The example shows properties configured from an external `Properties` file. At runtime, a `PropertyPlaceholderConfigurer` is applied to @@ -4268,7 +4043,6 @@ log4j and JSP EL style. The actual values come from another file in the standard Java `Properties` format: -==== [literal] [subs="verbatim,quotes"] ---- @@ -4277,7 +4051,6 @@ jdbc.url=jdbc:hsqldb:hsql://production:9002 jdbc.username=sa jdbc.password=root ---- -==== Therefore, the `${jdbc.username}` string is replaced at runtime with the value, 'sa', and the same applies for other placeholder values that match keys in the properties file. @@ -4288,13 +4061,11 @@ With the `context` namespace introduced in Spring 2.5, you can configure property placeholders with a dedicated configuration element. You can provide one or more locations as a comma-separated list in the `location` attribute, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== The `PropertyPlaceholderConfigurer` not only looks for properties in the `Properties` file you specify. By default, if it @@ -4316,7 +4087,6 @@ You can use the `PropertyPlaceholderConfigurer` to substitute class names, which sometimes useful when you have to pick a particular implementation class at runtime. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4331,7 +4101,6 @@ following example shows how to do so: ---- -==== If the class cannot be resolved at runtime to a valid class, resolution of the bean fails when it is about to be created, which is during the `preInstantiateSingletons()` @@ -4355,24 +4124,20 @@ values for the same bean property, the last one wins, due to the overriding mech Properties file configuration lines take the following format: -==== [literal] [subs="verbatim,quotes"] ---- beanName.property=value ---- -==== The following listing shows an example of the format: -==== [literal] [subs="verbatim,quotes"] ---- dataSource.driverClassName=com.mysql.jdbc.Driver dataSource.url=jdbc:mysql:mydb ---- -==== This example file can be used with a container definition that contains a bean called `dataSource` that has `driver` and `url` properties. @@ -4382,13 +4147,11 @@ except the final property being overridden is already non-null (presumably initi by the constructors). In the following example, the `sammy` property of the `bob` property of the `fred` property of the `tom` bean is set to the scalar value `123`: -==== [literal] [subs="verbatim,quotes"] ---- tom.fred.bob.sammy=123 ---- -==== NOTE: Specified override values are always literal values. They are not translated into @@ -4398,13 +4161,11 @@ definition specifies a bean reference. With the `context` namespace introduced in Spring 2.5, it is possible to configure property overriding with a dedicated configuration element, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== @@ -4492,7 +4253,6 @@ As always, you can register them as individual bean definitions, but they can al implicitly registered by including the following tag in an XML-based Spring configuration (notice the inclusion of the `context` namespace): -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4509,7 +4269,6 @@ configuration (notice the inclusion of the `context` namespace): ---- -==== (The implicitly registered post-processors include {api-spring-framework}/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.html[`AutowiredAnnotationBeanPostProcessor`], @@ -4535,7 +4294,6 @@ it only checks for `@Autowired` beans in your controllers, and not your services The `@Required` annotation applies to bean property setter methods, as in the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4551,7 +4309,6 @@ example: // ... } ---- -==== This annotation indicates that the affected bean property must be populated at configuration time, through an explicit property value in a bean definition or through @@ -4574,7 +4331,6 @@ examples included in this section. See <> for m You can apply the `@Autowired` annotation to constructors, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4590,7 +4346,6 @@ You can apply the `@Autowired` annotation to constructors, as the following exam // ... } ---- -==== [NOTE] ==== @@ -4603,7 +4358,6 @@ teach the container which one to use. You can also apply the `@Autowired` annotation to "`traditional`" setter methods, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4619,12 +4373,10 @@ methods, as the following example shows: // ... } ---- -==== You can also apply the annotation to methods with arbitrary names and multiple arguments, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4644,12 +4396,10 @@ arguments, as the following example shows: // ... } ---- -==== You can apply `@Autowired` to fields as well and even mix it with constructors, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4668,7 +4418,6 @@ following example shows: // ... } ---- -==== [TIP] ==== @@ -4688,7 +4437,6 @@ You can also provide all beans of a particular type from the `ApplicationContext` by adding the annotation to a field or method that expects an array of that type, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4700,11 +4448,9 @@ of that type, as the following example shows: // ... } ---- -==== The same applies for typed collections, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4720,7 +4466,6 @@ The same applies for typed collections, as the following example shows: // ... } ---- -==== [TIP] ==== @@ -4744,7 +4489,6 @@ Even typed `Map` instances can be autowired as long as the expected key type is values contain all beans of the expected type, and the keys contain the corresponding bean names, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4760,14 +4504,12 @@ corresponding bean names, as the following example shows: // ... } ---- -==== By default, the autowiring fails whenever zero candidate beans are available. The default behavior is to treat annotated methods, constructors, and fields as indicating required dependencies. You can change this behavior as demonstrated, in the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4783,7 +4525,6 @@ following example: // ... } ---- -==== [NOTE] ==== @@ -4802,7 +4543,6 @@ by the container. If no value is injected, a corresponding exception is raised. Alternatively, you can express the non-required nature of a particular dependency through Java 8's `java.util.Optional`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4814,12 +4554,10 @@ through Java 8's `java.util.Optional`, as the following example shows: } } ---- -==== As of Spring Framework 5.0, you can also use a `@Nullable` annotation (of any kind in any package -- for example, `javax.annotation.Nullable` from JSR-305): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4831,7 +4569,6 @@ in any package -- for example, `javax.annotation.Nullable` from JSR-305): } } ---- -==== You can also use `@Autowired` for interfaces that are well-known resolvable dependencies: `BeanFactory`, `ApplicationContext`, `Environment`, `ResourceLoader`, @@ -4878,7 +4615,6 @@ autowired value. Consider the following configuration that defines `firstMovieCatalog` as the primary `MovieCatalog`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4895,12 +4631,10 @@ primary `MovieCatalog`: // ... } ---- -==== With the preceding configuration, the following `MovieRecommender` is autowired with the `firstMovieCatalog`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4912,11 +4646,9 @@ With the preceding configuration, the following `MovieRecommender` is autowired // ... } ---- -==== The corresponding bean definitions follow: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4943,7 +4675,6 @@ The corresponding bean definitions follow: ---- -==== @@ -4957,7 +4688,6 @@ with specific arguments, narrowing the set of type matches so that a specific be chosen for each argument. In the simplest case, this can be a plain descriptive value, as shown in the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4970,12 +4700,10 @@ shown in the following example: // ... } ---- -==== You can also specify the `@Qualifier` annotation on individual constructor arguments or method parameters, as shown in the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4995,11 +4723,9 @@ method parameters, as shown in the following example: // ... } ---- -==== The following example shows corresponding bean definitions. -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5095,12 +4821,10 @@ narrowing through qualifier annotations at the parameter level. By contrast, `@R is supported only for fields and bean property setter methods with a single argument. As a consequence, you should stick with qualifiers if your injection target is a constructor or a multi-argument method. -==== You can create your own custom qualifier annotations. To do so, define an annotation and provide the `@Qualifier` annotation within your definition, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5112,12 +4836,10 @@ provide the `@Qualifier` annotation within your definition, as the following exa String value(); } ---- -==== Then you can provide the custom qualifier on autowired fields and parameters, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5137,7 +4859,6 @@ following example shows: // ... } ---- -==== Next, you can provide the information for the candidate bean definitions. You can add `` tags as sub-elements of the `` tag and then specify the `type` and @@ -5146,7 +4867,6 @@ fully-qualified class name of the annotation. Alternately, as a convenience if n conflicting names exists, you can use the short class name. The following example demonstrates both approaches: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5175,7 +4895,6 @@ demonstrates both approaches: ---- -==== In <>, you can see an annotation-based alternative to providing the qualifier metadata in XML. Specifically, see <>. @@ -5186,7 +4905,6 @@ several different types of dependencies. For example, you may provide an offline catalog that can be searched when no Internet connection is available. First, define the simple annotation, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5197,12 +4915,10 @@ the simple annotation, as the following example shows: } ---- -==== Then add the annotation to the field or property to be autowired, as shown in the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5216,11 +4932,10 @@ following example: } ---- <1> This line adds the `@Offline` annotation. -==== + Now the bean definition only needs a qualifier `type`, as shown in the following example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5230,7 +4945,7 @@ Now the bean definition only needs a qualifier `type`, as shown in the following ---- <1> This element specifies the qualifier. -==== + You can also define custom qualifier annotations that accept named attributes in addition to or instead of the simple `value` attribute. If multiple attribute values are @@ -5238,7 +4953,6 @@ then specified on a field or parameter to be autowired, a bean definition must m all such attribute values to be considered an autowire candidate. As an example, consider the following annotation definition: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5252,11 +4966,9 @@ consider the following annotation definition: Format format(); } ---- -==== In this case `Format` is an enum, defined as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5264,12 +4976,10 @@ In this case `Format` is an enum, defined as follows: VHS, DVD, BLURAY } ---- -==== The fields to be autowired are annotated with the custom qualifier and include values for both attributes: `genre` and `format`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5294,7 +5004,6 @@ for both attributes: `genre` and `format`, as the following example shows: // ... } ---- -==== Finally, the bean definitions should contain matching qualifier values. This example also demonstrates that you can use bean meta attributes instead of the @@ -5303,7 +5012,6 @@ precedence, but the autowiring mechanism falls back on the values provided withi `` tags if no such qualifier is present, as in the last two bean definitions in the following example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5348,7 +5056,6 @@ the following example: ---- -==== @@ -5359,7 +5066,6 @@ In addition to the `@Qualifier` annotation, you can use Java generic types as an implicit form of qualification. For example, suppose you have the following configuration: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5377,13 +5083,11 @@ configuration: } } ---- -==== Assuming that the preceding beans implement a generic interface, (that is, `Store` and `Store`), you can `@Autowire` the `Store` interface and the generic is used as a qualifier, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5393,12 +5097,10 @@ used as a qualifier, as the following example shows: @Autowired private Store s2; // qualifier, injects the integerStore bean ---- -==== Generic qualifiers also apply when autowiring lists, `Map` instances and arrays. The following example autowires a generic `List`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5407,7 +5109,6 @@ following example autowires a generic `List`: @Autowired private List> s; ---- -==== @@ -5419,7 +5120,6 @@ is a `BeanFactoryPostProcessor` that lets you register your own custom qualifier annotation types, even if they are not annotated with Spring's `@Qualifier` annotation. The following example shows how to use `CustomAutowireConfigurer`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5432,7 +5132,6 @@ The following example shows how to use `CustomAutowireConfigurer`: ---- -==== The `AutowireCandidateResolver` determines autowire candidates by: @@ -5459,7 +5158,6 @@ Spring-managed objects as well. bean name to be injected. In other words, it follows by-name semantics, as demonstrated in the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5474,14 +5172,13 @@ demonstrated in the following example: } ---- <1> This line injects a `@Resource`. -==== + If no name is explicitly specified, the default name is derived from the field name or setter method. In case of a field, it takes the field name. In case of a setter method, it takes the bean property name. The following example is going to have the bean named `movieFinder` injected into its setter method: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5495,7 +5192,6 @@ named `movieFinder` injected into its setter method: } } ---- -==== NOTE: The name provided with the annotation is resolved as a bean name by the `ApplicationContext` of which the `CommonAnnotationBeanPostProcessor` is aware. @@ -5514,7 +5210,6 @@ Thus, in the following example, the `customerPreferenceDao` field first looks fo named customerPreferenceDao and then falls back to a primary type match for the type `CustomerPreferenceDao`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5534,7 +5229,6 @@ named customerPreferenceDao and then falls back to a primary type match for the ---- <1> The `context` field is injected based on the known resolvable dependency type: `ApplicationContext`. -==== @@ -5552,7 +5246,6 @@ point in the lifecycle as the corresponding Spring lifecycle interface method or explicitly declared callback method. In the following example, the cache is pre-populated upon initialization and cleared upon destruction: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5569,7 +5262,6 @@ pre-populated upon initialization and cleared upon destruction: } } ---- -==== NOTE: For details about the effects of combining various lifecycle mechanisms, see <>. @@ -5634,7 +5326,6 @@ own code. A meta-annotation is an annotation that can be applied to another annotation. For example, the `@Service` annotation mentioned <> is meta-annotated with `@Component`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5648,7 +5339,7 @@ annotation. For example, the `@Service` annotation mentioned < The `Component` causes `@Service` to be treated in the same way as `@Component`. -==== + You can also combine meta-annotations to create "`composed annotations`". For example, the `@RestController` annotation from Spring MVC is composed of `@Controller` and @@ -5682,7 +5373,6 @@ customization of the `proxyMode`. The following listing shows the definition of You can then use `@SessionScope` without declaring the `proxyMode` as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5692,11 +5382,9 @@ You can then use `@SessionScope` without declaring the `proxyMode` as follows: // ... } ---- -==== You can also override the value for the `proxyMode`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5706,7 +5394,6 @@ You can also override the value for the `proxyMode`, as the following example sh // ... } ---- -==== For further details, see the https://github.com/spring-projects/spring-framework/wiki/Spring-Annotation-Programming-Model[Spring Annotation Programming Model] @@ -5721,7 +5408,6 @@ Spring can automatically detect stereotyped classes and register corresponding `BeanDefinition` instances with the `ApplicationContext`. For example, the following two classes are eligible for such autodetection: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5745,14 +5431,12 @@ are eligible for such autodetection: // implementation elided for clarity } ---- -==== To autodetect these classes and register the corresponding beans, you need to add `@ComponentScan` to your `@Configuration` class, where the `basePackages` attribute is a common parent package for the two classes. (Alternatively, you can specify a comma- or semicolon- or space-separated list that includes the parent package of each class.) -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5762,14 +5446,12 @@ comma- or semicolon- or space-separated list that includes the parent package of ... } ---- -==== NOTE: For brevity, the preceding example could have used the `value` attribute of the annotation (that is, `@ComponentScan("org.example")`). The following alternative uses XML: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5786,7 +5468,6 @@ The following alternative uses XML: ---- -==== TIP: The use of `` implicitly enables the functionality of ``. There is usually no need to include the @@ -5859,7 +5540,6 @@ and `expression` attributes. The following table describes the filtering options The following example shows the configuration ignoring all `@Repository` annotations and using "`stub`" repositories instead: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5871,11 +5551,9 @@ and using "`stub`" repositories instead: ... } ---- -==== The following listing shows the equivalent XML: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5888,7 +5566,6 @@ The following listing shows the equivalent XML: ---- -==== NOTE: You can also disable the default filters by setting `useDefaultFilters=false` on the annotation or by providing `use-default-filters="false"` as an attribute of the `` element. This, @@ -5904,7 +5581,6 @@ Spring components can also contribute bean definition metadata to the container. this with the same `@Bean` annotation used to define bean metadata within `@Configuration` annotated classes. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5922,7 +5598,6 @@ annotated classes. The following example shows how to do so: } } ---- -==== The preceding class is a Spring component that has application-specific code in its `doWork()` method. However, it also contributes a bean definition that has a factory @@ -5938,7 +5613,6 @@ leads to the injection of a lazy-resolution proxy. Autowired fields and methods are supported, as previously discussed, with additional support for autowiring of `@Bean` methods. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5976,7 +5650,6 @@ support for autowiring of `@Bean` methods. The following example shows how to do } } ---- -==== The example autowires the `String` method parameter `country` to the value of the `age` property on another bean named `privateInstance`. A Spring Expression Language element @@ -5995,7 +5668,6 @@ injection point that triggered the creation of a new bean instance in the given You can use the provided injection point metadata with semantic care in such scenarios. The following example shows how to do use `InjectionPoint`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6008,7 +5680,6 @@ The following example shows how to do use `InjectionPoint`: } } ---- -==== The `@Bean` methods in a regular Spring component are processed differently than their counterparts inside a Spring `@Configuration` class. The difference is that `@Component` @@ -6072,7 +5743,6 @@ If such an annotation contains no name `value` or for any other detected compone the uncapitalized non-qualified class name. For example, if the following component classes were detected, the names would be `myMovieLister` and `movieFinderImpl`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6090,7 +5760,6 @@ classes were detected, the names would be `myMovieLister` and `movieFinderImpl`: // ... } ---- -==== NOTE: If you do not want to rely on the default bean-naming strategy, you can provide a custom bean-naming strategy. First, implement the @@ -6099,7 +5768,6 @@ interface, and be sure to include a default no-arg constructor. Then, provide th qualified class name when configuring the scanner, as the following example annotation and bean definition show: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6118,7 +5786,6 @@ and bean definition show: name-generator="org.example.MyNameGenerator" /> ---- -==== As a general rule, consider specifying the name with the annotation whenever other components may be making explicit references to it. On the other hand, the @@ -6134,7 +5801,6 @@ autodetected components is `singleton`. However, sometimes you need a different that can be specified by the `@Scope` annotation. You can provide the name of the scope within the annotation, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6144,7 +5810,6 @@ scope within the annotation, as the following example shows: // ... } ---- -==== NOTE: `@Scope` annotations are only introspected on the concrete bean class (for annotated components) or the factory method (for `@Bean` methods). In contrast to XML bean @@ -6164,7 +5829,6 @@ interface. Be sure to include a default no-arg constructor. Then you can provide fully qualified class name when configuring the scanner, as the following example of both an annotation and a bean definition shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6182,7 +5846,6 @@ an annotation and a bean definition shows: ---- -==== When using certain non-singleton scopes, it may be necessary to generate proxies for the scoped objects. The reasoning is described in <>. @@ -6190,7 +5853,6 @@ For this purpose, a scoped-proxy attribute is available on the component-scan element. The three possible values are: `no`, `interfaces`, and `targetClass`. For example, the following configuration results in standard JDK dynamic proxies: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6208,7 +5870,6 @@ the following configuration results in standard JDK dynamic proxies: ---- -==== @@ -6225,7 +5886,6 @@ auto-detection of components, you can provide the qualifier metadata with type-l annotations on the candidate class. The following three examples demonstrate this technique: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6255,7 +5915,6 @@ technique: // ... } ---- -==== NOTE: As with most annotation-based alternatives, keep in mind that the annotation metadata is bound to the class definition itself, while the use of XML allows for multiple beans @@ -6280,7 +5939,6 @@ To generate the index, add an additional dependency to each module that contains components that are targets for component scan directives. The following example shows how to do so with Maven: -==== [source,xml,indent=0] [subs="verbatim,quotes,attributes"] ---- @@ -6293,11 +5951,9 @@ how to do so with Maven: ---- -==== The following example shows how to do so with Gradle: -==== [source,groovy,indent=0] [subs="verbatim,quotes,attributes"] ---- @@ -6305,7 +5961,6 @@ The following example shows how to do so with Gradle: compileOnly("org.springframework:spring-context-indexer:{spring-version}") } ---- -==== That process generates a `META-INF/spring.components` file that is included in the jar file. @@ -6337,7 +5992,6 @@ repository ( http://repo1.maven.org/maven2/javax/inject/javax.inject/1/[http://repo1.maven.org/maven2/javax/inject/javax.inject/1/]). You can add the following dependency to your file pom.xml: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6347,7 +6001,6 @@ You can add the following dependency to your file pom.xml: 1 ---- -==== ===== @@ -6357,7 +6010,6 @@ You can add the following dependency to your file pom.xml: Instead of `@Autowired`, you can use `@javax.inject.Inject` as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6378,7 +6030,6 @@ Instead of `@Autowired`, you can use `@javax.inject.Inject` as follows: } } ---- -==== As with `@Autowired`, you can use `@Inject` at the field level, method level and constructor-argument level. Furthermore, you may declare your injection point as a @@ -6386,7 +6037,6 @@ and constructor-argument level. Furthermore, you may declare your injection poin other beans through a `Provider.get()` call. The following example offers a variant of the preceding example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6408,12 +6058,10 @@ preceding example: } } ---- -==== If you would like to use a qualified name for the dependency that should be injected, you should use the `@Named` annotation, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6432,14 +6080,12 @@ you should use the `@Named` annotation, as the following example shows: // ... } ---- -==== As with `@Autowired`, `@Inject` can also be used with `java.util.Optional` or `@Nullable`. This is even more applicable here, since `@Inject` does not have a `required` attribute. The following pair of examples show how to use `@Inject` and `@Nullable`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6463,7 +6109,6 @@ a `required` attribute. The following pair of examples show how to use `@Inject` } } ---- -==== @@ -6473,7 +6118,6 @@ a `required` attribute. The following pair of examples show how to use `@Inject` Instead of `@Component`, you can use `@javax.inject.Named` or `javax.annotation.ManagedBean`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6493,12 +6137,10 @@ as the following example shows: // ... } ---- -==== It is very common to use `@Component` without specifying a name for the component. `@Named` can be used in a similar fashion, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6518,12 +6160,10 @@ It is very common to use `@Component` without specifying a name for the componen // ... } ---- -==== When you use `@Named` or `@ManagedBean`, you can use component scanning in the exact same way as when you use Spring annotations, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6533,7 +6173,6 @@ exact same way as when you use Spring annotations, as the following example show ... } ---- -==== NOTE: In contrast to `@Component`, the JSR-330 `@Named` and the JSR-250 `ManagedBean` annotations are not composable. You should use Spring's stereotype model for building @@ -6631,7 +6270,6 @@ source of bean definitions. Furthermore, `@Configuration` classes let inter-bean dependencies be defined by calling other `@Bean` methods in the same class. The simplest possible `@Configuration` class reads as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6644,11 +6282,9 @@ The simplest possible `@Configuration` class reads as follows: } } ---- -==== The preceding `AppConfig` class is equivalent to the following Spring `` XML: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6656,7 +6292,6 @@ The preceding `AppConfig` class is equivalent to the following Spring `` ---- -==== .Full @Configuration vs "`lite`" @Bean mode? **** @@ -6714,7 +6349,6 @@ In much the same way that Spring XML files are used as input when instantiating instantiating an `AnnotationConfigApplicationContext`. This allows for completely XML-free usage of the Spring container, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6724,13 +6358,11 @@ XML-free usage of the Spring container, as the following example shows: myService.doStuff(); } ---- -==== As mentioned earlier, `AnnotationConfigApplicationContext` is not limited to working only with `@Configuration` classes. Any `@Component` or JSR-330 annotated class may be supplied as input to the constructor, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6740,7 +6372,6 @@ as input to the constructor, as the following example shows: myService.doStuff(); } ---- -==== The preceding example assumes that `MyServiceImpl`, `Dependency1`, and `Dependency2` use Spring dependency injection annotations such as `@Autowired`. @@ -6754,7 +6385,6 @@ and then configure it by using the `register()` method. This approach is particu when programmatically building an `AnnotationConfigApplicationContext`. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6767,7 +6397,6 @@ example shows how to do so: myService.doStuff(); } ---- -==== [[beans-java-instantiating-container-scan]] @@ -6775,7 +6404,6 @@ example shows how to do so: To enable component scanning, you can annotate your `@Configuration` class as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6786,14 +6414,13 @@ To enable component scanning, you can annotate your `@Configuration` class as fo } ---- <1> This annotation enables component scanning. -==== + [TIP] ===== Experienced Spring users may be familiar with the XML declaration equivalent from Spring's `context:` namespace, shown in the following example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6801,7 +6428,6 @@ Spring's `context:` namespace, shown in the following example: ---- -==== ===== In the preceding example, the `com.acme` package is scanned to look for any @@ -6810,7 +6436,6 @@ definitions within the container. `AnnotationConfigApplicationContext` exposes t `scan(String...)` method to allow for the same component-scanning functionality, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6821,7 +6446,6 @@ following example shows: MyService myService = ctx.getBean(MyService.class); } ---- -==== NOTE: Remember that `@Configuration` classes are <> with `@Component`, so they are candidates for component-scanning. In the preceding example, @@ -6840,7 +6464,6 @@ configuring the Spring `ContextLoaderListener` servlet listener, Spring MVC Spring MVC web application (note the use of the `contextClass` context-param and init-param): -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6894,7 +6517,6 @@ init-param): ---- -==== @@ -6920,7 +6542,6 @@ method to register a bean definition within an `ApplicationContext` of the type specified as the method's return value. By default, the bean name is the same as the method name. The following example shows a `@Bean` method declaration: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6933,11 +6554,9 @@ the method name. The following example shows a `@Bean` method declaration: } } ---- -==== The preceding configuration is exactly equivalent to the following Spring XML: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6945,24 +6564,20 @@ The preceding configuration is exactly equivalent to the following Spring XML: ---- -==== Both declarations make a bean named `transferService` available in the `ApplicationContext`, bound to an object instance of type `TransferServiceImpl`, as the following text image shows: -==== [literal] [subs="verbatim,quotes"] ---- transferService -> com.acme.TransferServiceImpl ---- -==== You can also declare your `@Bean` method with an interface (or base class) return type, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6975,7 +6590,6 @@ return type, as the following example shows: } } ---- -==== However, this limits the visibility for advance type prediction to the specified interface type (`TransferService`). Then, with the full type (`TransferServiceImpl`) @@ -7000,7 +6614,6 @@ dependencies required to build that bean. For instance, if our `TransferService` requires an `AccountRepository`, we can materialize that dependency with a method parameter, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7013,7 +6626,6 @@ parameter, as the following example shows: } } ---- -==== The resolution mechanism is pretty much identical to constructor-based dependency injection. See <> for more details. @@ -7040,7 +6652,6 @@ The `@Bean` annotation supports specifying arbitrary initialization and destruct callback methods, much like Spring XML's `init-method` and `destroy-method` attributes on the `bean` element, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7072,7 +6683,6 @@ on the `bean` element, as the following example shows: } } ---- -==== [NOTE] ===== @@ -7089,7 +6699,6 @@ for a `DataSource`, as it is known to be problematic on Java EE application serv The following example shows how to prevent an automatic destruction callback for a `DataSource`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7098,7 +6707,6 @@ The following example shows how to prevent an automatic destruction callback for return (DataSource) jndiTemplate.lookup("MyDS"); } ---- -==== Also, with `@Bean` methods, you typically use programmatic JNDI lookups, either by using Spring's `JndiTemplate` or `JndiLocatorDelegate` helpers or straight JNDI @@ -7111,7 +6719,6 @@ intend to refer to the provided resource here). In the case of `BeanOne` from the example above the preceding note, it would be equally valid to call the `init()` method directly during construction, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7128,7 +6735,6 @@ method directly during construction, as the following example shows: // ... } ---- -==== TIP: When you work directly in Java, you can do anything you like with your objects and do not always need to rely on the container lifecycle. @@ -7149,7 +6755,6 @@ specific scope. You can use any of the standard scopes specified in the The default scope is `singleton`, but you can override this with the `@Scope` annotation, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7163,7 +6768,6 @@ as the following example shows: } } ---- -==== [[beans-java-scoped-proxy]] ===== `@Scope` and `scoped-proxy` @@ -7178,7 +6782,6 @@ specify `ScopedProxyMode.TARGET_CLASS` or `ScopedProxyMode.INTERFACES`. If you port the scoped proxy example from the XML reference documentation (see <>) to our `@Bean` using Java, it resembles the following: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7197,7 +6800,6 @@ If you port the scoped proxy example from the XML reference documentation (see return service; } ---- -==== [[beans-java-customizing-bean-naming]] @@ -7207,7 +6809,6 @@ By default, configuration classes use a `@Bean` method's name as the name of the resulting bean. This functionality can be overridden, however, with the `name` attribute, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7220,7 +6821,6 @@ as the following example shows: } } ---- -==== [[beans-java-bean-aliasing]] @@ -7231,7 +6831,6 @@ multiple names, otherwise known as bean aliasing. The `name` attribute of the `@ annotation accepts a String array for this purpose. The following example shows how to set a number of aliases for a bean: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7244,7 +6843,6 @@ a number of aliases for a bean: } } ---- -==== [[beans-java-bean-description]] @@ -7257,7 +6855,6 @@ To add a description to a `@Bean`, you can use the {api-spring-framework}/context/annotation/Description.html[`@Description`] annotation, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7271,7 +6868,6 @@ annotation, as the following example shows: } } ---- -==== @@ -7290,7 +6886,6 @@ inter-bean dependencies. See <> for a general introdu When beans have dependencies on one another, expressing that dependency is as simple as having one bean method call another, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7308,7 +6903,6 @@ as having one bean method call another, as the following example shows: } } ---- -==== In the preceding example, `beanOne` receives a reference to `beanTwo` through constructor injection. @@ -7328,7 +6922,6 @@ singleton-scoped bean has a dependency on a prototype-scoped bean. Using Java fo type of configuration provides a natural means for implementing this pattern. The following example shows how to use lookup method injection: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7345,13 +6938,11 @@ following example shows how to use lookup method injection: protected abstract Command createCommand(); } ---- -==== By using Java configuration, you can create a subclass of `CommandManager` where the abstract `createCommand()` method is overridden in such a way that it looks up a new (prototype) command object. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7374,7 +6965,6 @@ the abstract `createCommand()` method is overridden in such a way that it looks } } ---- -==== [[beans-java-further-information-java-config]] @@ -7382,7 +6972,6 @@ the abstract `createCommand()` method is overridden in such a way that it looks Consider the following example, which shows a `@Bean` annotated method being called twice: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7409,7 +6998,6 @@ Consider the following example, which shows a `@Bean` annotated method being cal } } ---- -==== `clientDao()` has been called once in `clientService1()` and once in `clientService2()`. Since this method creates a new instance of `ClientDaoImpl` and returns it, you would @@ -7458,7 +7046,6 @@ Much as the `` element is used within Spring XML files to aid in modula configurations, the `@Import` annotation allows for loading `@Bean` definitions from another configuration class, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7481,13 +7068,11 @@ another configuration class, as the following example shows: } } ---- -==== Now, rather than needing to specify both `ConfigA.class` and `ConfigB.class` when instantiating the context, only `ConfigB` needs to be supplied explicitly, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7499,7 +7084,6 @@ following example shows: B b = ctx.getBean(B.class); } ---- -==== This approach simplifies container instantiation, as only one class needs to be dealt with, rather than requiring you to remember a potentially large number of @@ -7525,7 +7109,6 @@ a `@Bean` method can have an arbitrary number of parameters that describe the be dependencies. Consider the following more real-world scenario with several `@Configuration` classes, each depending on beans declared in the others: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7564,7 +7147,6 @@ classes, each depending on beans declared in the others: transferService.transfer(100.00, "A123", "C456"); } ---- -==== There is another way to achieve the same result. Remember that `@Configuration` classes are ultimately only another bean in the container: This means that they can take advantage of @@ -7585,7 +7167,6 @@ work on the configuration class itself, since it is being created as a bean inst The following example shows how one bean can be autowired to another bean: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7634,7 +7215,6 @@ The following example shows how one bean can be autowired to another bean: transferService.transfer(100.00, "A123", "C456"); } ---- -==== TIP: Constructor injection in `@Configuration` classes is only supported as of Spring Framework 4.3. Note also that there is no need to specify `@Autowired` if the target @@ -7657,7 +7237,6 @@ In cases where this ambiguity is not acceptable and you wish to have direct navi from within your IDE from one `@Configuration` class to another, consider autowiring the configuration classes themselves. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7674,14 +7253,12 @@ configuration classes themselves. The following example shows how to do so: } } ---- -==== In the preceding situation, where `AccountRepository` is defined is completely explicit. However, `ServiceConfig` is now tightly coupled to `RepositoryConfig`. That is the tradeoff. This tight coupling can be somewhat mitigated by using interface-based or abstract class-based `@Configuration` classes. Consider the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7730,7 +7307,6 @@ abstract class-based `@Configuration` classes. Consider the following example: transferService.transfer(100.00, "A123", "C456"); } ---- -==== Now `ServiceConfig` is loosely coupled with respect to the concrete `DefaultRepositoryConfig`, and built-in IDE tooling is still useful: You can easily @@ -7764,7 +7340,6 @@ Implementations of the `Condition` interface provide a `matches(...)` method that returns `true` or `false`. For example, the following listing shows the actual `Condition` implementation used for `@Profile`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7785,7 +7360,6 @@ method that returns `true` or `false`. For example, the following listing shows return true; } ---- -==== See the {api-spring-framework}/context/annotation/Conditional.html[`@Conditional`] javadoc for more detail. @@ -7822,7 +7396,6 @@ properly. The following example shows an ordinary configuration class in Java: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7843,11 +7416,9 @@ The following example shows an ordinary configuration class in Java: } } ---- -==== The following example shows part of a sample `system-test-config.xml` file: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -7865,11 +7436,9 @@ The following example shows part of a sample `system-test-config.xml` file: ---- -==== The following example shows a possible `jdbc.properties` file: -==== [literal] [subs="verbatim,quotes"] ---- @@ -7887,7 +7456,6 @@ jdbc.password= // ... } ---- -==== NOTE: In `system-test-config.xml` file, the `AppConfig` `` does not declare an `id` element. While it would be acceptable to do so, it is unnecessary, given that no other bean @@ -7907,7 +7475,6 @@ functionality. The following example shows the modified `system-test-config.xml` file: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -7923,7 +7490,6 @@ The following example shows the modified `system-test-config.xml` file: ---- -==== -- [[beans-java-combining-java-centric]] @@ -7938,7 +7504,6 @@ that defines a bean, a properties file, and the `main` class) shows how to use the `@ImportResource` annotation to achieve "`Java-centric`" configuration that uses XML as needed: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7989,7 +7554,6 @@ jdbc.password= // ... } ---- -==== @@ -8034,7 +7598,6 @@ B deployments. Consider the first use case in a practical application that requires a `DataSource`. In a test environment, the configuration might resemble the following: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -8047,14 +7610,12 @@ Consider the first use case in a practical application that requires a .build(); } ---- -==== Now consider how this application can be deployed into a QA or production environment, assuming that the datasource for the application is registered with the production application server's JNDI directory. Our `dataSource` bean now looks like the following listing: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -8064,7 +7625,6 @@ now looks like the following listing: return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource"); } ---- -==== The problem is how to switch between using these two variations based on the current environment. Over time, Spring users have devised a number of ways to @@ -8089,7 +7649,6 @@ annotation lets you indicate that a component is eligible for registration when one or more specified profiles are active. Using our preceding example, we can rewrite the `dataSource` configuration as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -8122,7 +7681,6 @@ can rewrite the `dataSource` configuration as follows: } } ---- -==== NOTE: As mentioned earlier, with `@Bean` methods, you typically choose to use programmatic JNDI lookups, by using either Spring's `JndiTemplate`/`JndiLocatorDelegate` helpers or the @@ -8147,7 +7705,6 @@ of creating a custom composed annotation. The following example defines a custom `@Production` annotation that you can use as a drop-in replacement for `@Profile("production")`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -8157,7 +7714,6 @@ of creating a custom composed annotation. The following example defines a custom public @interface Production { } ---- -==== TIP: If a `@Configuration` class is marked with `@Profile`, all of the `@Bean` methods and `@Import` annotations associated with that class are bypassed unless one or more of @@ -8172,7 +7728,6 @@ active. For example, given `@Profile({"p1", "!p2"})`, registration will occur if of a configuration class (for example, for alternative variants of a particular bean), as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -8218,7 +7773,6 @@ attribute, as shown in the preceding example. If the argument signatures are all the same (for example, all of the variants have no-arg factory methods), this is the only way to represent such an arrangement in a valid Java class in the first place (since there can only be one method of a particular name and argument signature). -==== [[beans-definition-profiles-xml]] @@ -8227,7 +7781,6 @@ way to represent such an arrangement in a valid Java class in the first place The XML counterpart is the `profile` attribute of the `` element. Our preceding sample configuration can be rewritten in two XML files, as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -8256,12 +7809,10 @@ configuration can be rewritten in two XML files, as follows: ---- -==== It is also possible to avoid that split and nest `` elements within the same file, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -8285,7 +7836,6 @@ as the following example shows: ---- -==== The `spring-bean.xsd` has been constrained to allow such elements only as the last ones in the file. This should help provide flexibility without incurring @@ -8297,7 +7847,6 @@ The XML counterpart does not support the profile expressions described earlier. however, to negate a profile by using the `!` operator. It is also possible to apply a logical "`and`" by nesting the profiles, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -8316,7 +7865,6 @@ however, to negate a profile by using the `!` operator. It is also possible to a ---- -==== In the preceding example, the `dataSource` bean is exposed if both the `production` and `us-east` profiles are active. @@ -8335,7 +7883,6 @@ Activating a profile can be done in several ways, but the most straightforward i it programmatically against the `Environment` API which is available through an `ApplicationContext`. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -8344,7 +7891,6 @@ it programmatically against the `Environment` API which is available through an ctx.register(SomeConfig.class, StandaloneDataConfig.class, JndiDataConfig.class); ctx.refresh(); ---- -==== In addition, you can also declaratively activate profiles through the `spring.profiles.active` property, which may be specified through system environment @@ -8359,24 +7905,20 @@ profiles at once. Programmatically, you can provide multiple profile names to th `setActiveProfiles()` method, which accepts `String...` varargs. The following example activates multiple profiles: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- ctx.getEnvironment().setActiveProfiles("profile1", "profile2"); ---- -==== Declaratively, `spring.profiles.active` may accept a comma-separated list of profile names, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- -Dspring.profiles.active="profile1,profile2" ---- -==== [[beans-definition-profiles-default]] @@ -8385,7 +7927,6 @@ as the following example shows: The default profile represents the profile that is enabled by default. Consider the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -8402,7 +7943,6 @@ following example: } } ---- -==== If no profile is active, the `dataSource` is created. You can see this as a way to provide a default definition for one or more beans. If any @@ -8419,7 +7959,6 @@ the `Environment` or ,declaratively, by using the `spring.profiles.default` prop Spring's `Environment` abstraction provides search operations over a configurable hierarchy of property sources. Consider the following listing: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -8428,7 +7967,6 @@ Environment env = ctx.getEnvironment(); boolean containsMyProperty = env.containsProperty("my-property"); System.out.println("Does my environment contain the 'my-property' property? " + containsMyProperty); ---- -==== In the preceding snippet, we see a high-level way of asking Spring whether the `my-property` property is defined for the current environment. To answer this question, the `Environment` object performs @@ -8472,7 +8010,6 @@ of properties that you want to integrate into this search. To do so, implement and instantiate your own `PropertySource` and add it to the set of `PropertySources` for the current `Environment`. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -8480,7 +8017,6 @@ ConfigurableApplicationContext ctx = new GenericApplicationContext(); MutablePropertySources sources = ctx.getEnvironment().getPropertySources(); sources.addFirst(new MyPropertySource()); ---- -==== In the preceding code, `MyPropertySource` has been added with highest precedence in the search. If it contains a `my-property` property, the property is detected and returned, in favor of @@ -8502,7 +8038,6 @@ Given a file called `app.properties` that contains the key-value pair `testbean. the following `@Configuration` class uses `@PropertySource` in such a way that a call to `testBean.getName()` returns `myTestBean`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -8521,13 +8056,11 @@ a call to `testBean.getName()` returns `myTestBean`: } } ---- -==== Any `${...}` placeholders present in a `@PropertySource` resource location are resolved against the set of property sources already registered against the environment, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -8546,7 +8079,6 @@ environment, as the following example shows: } } ---- -==== Assuming that `my.placeholder` is present in one of the property sources already registered (for example, system properties or environment variables), the placeholder is @@ -8576,7 +8108,6 @@ own property sources to the mix, as appropriate. Concretely, the following statement works regardless of where the `customer` property is defined, as long as it is available in the `Environment`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -8584,7 +8115,6 @@ property is defined, as long as it is available in the `Environment`: ---- -==== @@ -8598,7 +8128,6 @@ loaded into the Java virtual machine (JVM). To enable load-time weaving, you can add the `@EnableLoadTimeWeaving` to one of your `@Configuration` classes, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -8607,11 +8136,9 @@ To enable load-time weaving, you can add the `@EnableLoadTimeWeaving` to one of public class AppConfig { } ---- -==== Alternatively, for XML configuration, you can use the `context:load-time-weaver` element: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -8619,7 +8146,6 @@ Alternatively, for XML configuration, you can use the `context:load-time-weaver` ---- -==== Once configured for the `ApplicationContext`, any bean within that `ApplicationContext` may implement `LoadTimeWeaverAware`, thereby receiving a reference to the load-time @@ -8694,7 +8220,6 @@ Spring provides two `MessageSource` implementations, `ResourceBundleMessageSourc messaging. The `StaticMessageSource` is rarely used but provides programmatic ways to add messages to the source. The following example shows `ResourceBundleMessageSource`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -8711,7 +8236,6 @@ add messages to the source. The following example shows `ResourceBundleMessageSo ---- -==== The example assumes that you have three resource bundles called `format`, `exceptions` and `windows` defined in your classpath. Any request to resolve a message is @@ -8719,7 +8243,6 @@ handled in the JDK-standard way of resolving messages through `ResourceBundle` o purposes of the example, assume the contents of two of the above resource bundle files are as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -8733,13 +8256,11 @@ are as follows: # in exceptions.properties argument.required=The {0} argument is required. ---- -==== The next example shows a program to execute the `MessageSource` functionality. Remember that all `ApplicationContext` implementations are also `MessageSource` implementations and so can be cast to the `MessageSource` interface. -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -8749,17 +8270,14 @@ implementations and so can be cast to the `MessageSource` interface. System.out.println(message); } ---- -==== The resulting output from the above program is as follows: -==== [literal] [subs="verbatim,quotes"] ---- Alligators rock! ---- -==== To summarize, the `MessageSource` is defined in a file called `beans.xml`, which exists at the root of your classpath. The `messageSource` bean definition refers to a @@ -8771,7 +8289,6 @@ classpath and are called `format.properties`, `exceptions.properties`, and The next example shows arguments passed to the message lookup. These arguments are converted into `String` objects and inserted into placeholders in the lookup message. -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -8808,17 +8325,14 @@ converted into `String` objects and inserted into placeholders in the lookup mes } } ---- -==== The resulting output from the invocation of the `execute()` method is as follows: -==== [literal] [subs="verbatim,quotes"] ---- The userDao argument is required. ---- -==== With regard to internationalization ("`i18n`"), Spring's various `MessageSource` implementations follow the same locale resolution and fallback rules as the standard JDK @@ -8831,7 +8345,6 @@ Typically, locale resolution is managed by the surrounding environment of the application. In the following example, the locale against which (British) messages are resolved is specified manually: -==== [literal] [subs="verbatim,quotes"] ---- @@ -8849,17 +8362,14 @@ argument.required=Ebagum lad, the {0} argument is required, I say, required. System.out.println(message); } ---- -==== The resulting output from the running of the above program is as follows: -==== [literal] [subs="verbatim,quotes"] ---- Ebagum lad, the 'userDao' argument is required, I say, required. ---- -==== You can also use the `MessageSourceAware` interface to acquire a reference to any `MessageSource` that has been defined. Any bean that is defined in an @@ -8939,7 +8449,6 @@ The following table describes the standard events that Spring provides: You can also create and publish your own custom events. The following example shows a simple class that extends Spring's `ApplicationEvent` base class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -8957,14 +8466,12 @@ simple class that extends Spring's `ApplicationEvent` base class: // accessor and other methods... } ---- -==== To publish a custom `ApplicationEvent`, call the `publishEvent()` method on an `ApplicationEventPublisher`. Typically, this is done by creating a class that implements `ApplicationEventPublisherAware` and registering it as a Spring bean. The following example shows such a class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -8990,7 +8497,6 @@ example shows such a class: } } ---- -==== At configuration time, the Spring container detects that `EmailService` implements `ApplicationEventPublisherAware` and automatically calls @@ -9002,7 +8508,6 @@ To receive the custom `ApplicationEvent`, you can create a class that implements `ApplicationListener` and register it as a Spring bean. The following example shows such a class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -9019,7 +8524,6 @@ shows such a class: } } ---- -==== Notice that `ApplicationListener` is generically parameterized with the type of your custom event (`BlackListEvent` in the preceding example). This means that the `onApplicationEvent()` method can @@ -9035,7 +8539,6 @@ event publication becomes necessary, See the javadoc for Spring's The following example shows the bean definitions used to register and configure each of the classes above: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -9053,7 +8556,6 @@ the classes above: ---- -==== Putting it all together, when the `sendEmail()` method of the `emailService` bean is called, if there are any email messages that should be blacklisted, a custom event of type @@ -9077,7 +8579,6 @@ As of Spring 4.2, you can register an event listener on any public method of a m bean by using the `EventListener` annotation. The `BlackListNotifier` can be rewritten as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -9095,7 +8596,6 @@ follows: } } ---- -==== The method signature once again declares the event type to which it listens, but, this time, with a flexible name and without implementing a specific listener interface. @@ -9106,7 +8606,6 @@ If your method should listen to several events or if you want to define it with parameter at all, the event types can also be specified on the annotation itself. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -9115,7 +8614,6 @@ following example shows how to do so: ... } ---- -==== It is also possible to add additional runtime filtering by using the `condition` attribute of the annotation that defines a <> , which should match to actually @@ -9124,7 +8622,6 @@ invoke the method for a particular event. The following example shows how our notifier can be rewritten to be invoked only if the `content` attribute of the event is equal to `my-event`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -9133,7 +8630,6 @@ of the event is equal to `my-event`: // notify appropriate parties via notificationAddress... } ---- -==== Each `SpEL` expression evaluates against a dedicated context. The following table lists the items made available to the context so that you can use them for conditional event processing: @@ -9167,7 +8663,6 @@ signature actually refers to an arbitrary object that was published. If you need to publish an event as the result of processing another event, you can change the method signature to return the event that should be published, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -9177,7 +8672,6 @@ method signature to return the event that should be published, as the following // then publish a ListUpdateEvent... } ---- -==== NOTE: This feature is not supported for <>. @@ -9194,7 +8688,6 @@ If you want a particular listener to process events asynchronously, you can reus <>. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -9204,7 +8697,6 @@ following example shows how to do so: // BlackListEvent is processed in a separate thread } ---- -==== Be aware of the following limitations when using asynchronous events: @@ -9221,7 +8713,6 @@ Be aware of the following limitations when using asynchronous events: If you need one listener to be invoked before another one, you can add the `@Order` annotation to the method declaration, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -9231,7 +8722,6 @@ annotation to the method declaration, as the following example shows: // notify appropriate parties via notificationAddress... } ---- -==== [[context-functionality-events-generics]] @@ -9242,7 +8732,6 @@ You can also use generics to further define the structure of your event. Conside can create the following listener definition to receive only `EntityCreatedEvent` for a `Person`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -9251,7 +8740,6 @@ can create the following listener definition to receive only `EntityCreatedEvent ... } ---- -==== Due to type erasure, this works only if the event that is fired resolves the generic parameters on which the event listener filters (that is, something like @@ -9262,7 +8750,6 @@ structure (as should be the case for the event in the preceding example). In suc you can implement `ResolvableTypeProvider` to guide the framework beyond what the runtime environment provides. The following event shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -9278,7 +8765,6 @@ environment provides. The following event shows how to do so: } } ---- -==== TIP: This works not only for `ApplicationEvent` but any arbitrary object that you send as an event. @@ -9329,7 +8815,6 @@ programmatically by using one of the `ApplicationContext` implementations. You can register an `ApplicationContext` by using the `ContextLoaderListener`, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -9342,7 +8827,6 @@ following example shows: org.springframework.web.context.ContextLoaderListener ---- -==== The listener inspects the `contextConfigLocation` parameter. If the parameter does not exist, the listener uses `/WEB-INF/applicationContext.xml` as a default. When the @@ -9490,7 +8974,6 @@ The following table lists features provided by the `BeanFactory` and To explicitly register a bean post-processor with a `DefaultListableBeanFactory`, you need to programmatically call `addBeanPostProcessor`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -9503,12 +8986,10 @@ you need to programmatically call `addBeanPostProcessor`, as the following examp // now start using the factory ---- -==== To apply a `BeanFactoryPostProcessor` to a plain `DefaultListableBeanFactory`, you need to call its `postProcessBeanFactory` method, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -9523,7 +9004,6 @@ you need to call its `postProcessBeanFactory` method, as the following example s // now actually do the replacement cfg.postProcessBeanFactory(factory); ---- -==== In both cases, the explicit registration steps are inconvenient, which is why the various `ApplicationContext` variants are preferred over a plain diff --git a/src/docs/asciidoc/core/core-databuffer-codec.adoc b/src/docs/asciidoc/core/core-databuffer-codec.adoc index e23c07ebfd..2669c844ed 100644 --- a/src/docs/asciidoc/core/core-databuffer-codec.adoc +++ b/src/docs/asciidoc/core/core-databuffer-codec.adoc @@ -141,7 +141,6 @@ An `Encoder` allocates data buffers that others must read (and release). So an ` doesn't have much to do. However an `Encoder` must take care to release a data buffer if a serialization error occurs while populating the buffer with data. For example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -158,7 +157,6 @@ a serialization error occurs while populating the buffer with data. For example: } return buffer; ---- -==== The consumer of an `Encoder` is responsible for releasing the data buffers it receives. In a WebFlux application, the output of the `Encoder` is used to write to the HTTP server diff --git a/src/docs/asciidoc/core/core-expressions.adoc b/src/docs/asciidoc/core/core-expressions.adoc index e420a02c73..ba8f238ad0 100644 --- a/src/docs/asciidoc/core/core-expressions.adoc +++ b/src/docs/asciidoc/core/core-expressions.adoc @@ -65,7 +65,6 @@ The complete language reference can be found in The following code introduces the SpEL API to evaluate the literal string expression, `Hello World`. -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -74,7 +73,7 @@ The following code introduces the SpEL API to evaluate the literal string expres String message = (String) exp.getValue(); ---- <1> The value of the message variable is `'Hello World'`. -==== + The SpEL classes and interfaces you are most likely to use are located in the `org.springframework.expression` package and its sub-packages, such as `spel.support`. @@ -91,7 +90,6 @@ and calling constructors. In the following example of method invocation, we call the `concat` method on the string literal: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -100,11 +98,10 @@ In the following example of method invocation, we call the `concat` method on th String message = (String) exp.getValue(); ---- <1> The value of `message` is now 'Hello World!'. -==== + The following example of calling a JavaBean property calls the `String` property `Bytes`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -115,13 +112,12 @@ The following example of calling a JavaBean property calls the `String` property byte[] bytes = (byte[]) exp.getValue(); ---- <1> This line converts the literal to a byte array. -==== + SpEL also supports nested properties by using standard dot notation (such as `prop1.prop2.prop3`) and the setting of property values. Public fields may also be accessed. The following example shows how to use dot notation to get the length of a literal: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -132,12 +128,11 @@ The following example shows how to use dot notation to get the length of a liter int length = (Integer) exp.getValue(); ---- <1> `'Hello World'.bytes.length` gives the length of the literal. -==== + The String's constructor can be called instead of using a string literal, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -146,7 +141,7 @@ example shows: String message = exp.getValue(String.class); ---- <1> Construct a new `String` from the literal and make it be upper case. -==== + Note the use of the generic method: `public T getValue(Class desiredResultType)`. Using this method removes the need to cast the value of the expression to the desired @@ -158,7 +153,6 @@ against a specific object instance (called the root object). The following examp how to retrieve the `name` property from an instance of the `Inventor` class or create a boolean condition: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -180,7 +174,6 @@ create a boolean condition: // result == true ---- <1> Parse `name` as an expression. -==== @@ -228,7 +221,6 @@ to set a `List` property. The type of the property is actually `List`. recognizes that the elements of the list need to be converted to `Boolean` before being placed in it. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -248,7 +240,6 @@ being placed in it. The following example shows how to do so: // b is false Boolean b = simple.booleanList.get(0); ---- -==== @@ -265,7 +256,6 @@ and specifying an index that is beyond the end of the current size of the array list, you can automatically grow the array or list to accommodate that index. The following example demonstrates how to automatically grow the list: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -289,7 +279,6 @@ example demonstrates how to automatically grow the list: // demo.list will now be a real collection of 4 entries // Each entry is a new empty String ---- -==== @@ -317,11 +306,9 @@ on repeated evaluations. Consider the following basic expression: -==== ---- someArray[0].someProperty.someOtherProperty < 0.1 ---- -==== Because the preceding expression involves array access, some property de-referencing, and numeric operations, the performance gain can be very noticeable. In an example @@ -361,7 +348,6 @@ since part of the expression may be running twice. After selecting a mode, use the `SpelParserConfiguration` to configure the parser. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -376,7 +362,6 @@ following example shows how to do so: Object payload = expr.getValue(message); ---- -==== When you specify the compiler mode, you can also specify a classloader (passing null is allowed). Compiled expressions are defined in a child classloader created under any that is supplied. @@ -425,7 +410,6 @@ form `#{ }`. A property or constructor argument value can be set by using expressions, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -435,12 +419,10 @@ example shows: ---- -==== The `systemProperties` variable is predefined, so you can use it in your expressions, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -450,14 +432,12 @@ the following example shows: ---- -==== Note that you do not have to prefix the predefined variable with the `#` symbol in this context. You can also refer to other bean properties by name, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -473,7 +453,6 @@ You can also refer to other bean properties by name, as the following example sh ---- -==== @@ -485,7 +464,6 @@ parameters. The following example sets the default value of a field variable: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -504,11 +482,9 @@ The following example sets the default value of a field variable: } ---- -==== The following example shows the equivalent but on a property setter method: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -527,12 +503,10 @@ The following example shows the equivalent but on a property setter method: } ---- -==== Autowired methods and constructors can also use the `@Value` annotation, as the following examples show: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -571,7 +545,6 @@ examples show: // ... } ---- -==== @@ -611,7 +584,6 @@ The following listing shows simple usage of literals. Typically, they are not us in isolation like this but, rather, as part of a more complex expression -- for example, using a literal on one side of a logical comparison operator. -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -629,7 +601,6 @@ using a literal on one side of a logical comparison operator. Object nullValue = parser.parseExpression("null").getValue(); ---- -==== Numbers support the use of the negative sign, exponential notation, and decimal points. By default, real numbers are parsed by using Double.parseDouble(). @@ -645,7 +616,6 @@ data listed in the <> To navigate "`down`" and get Tesla's year of birth and Pupin's city of birth, we use the following expressions: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -654,13 +624,11 @@ expressions: String city = (String) parser.parseExpression("placeOfBirth.City").getValue(context); ---- -==== Case insensitivity is allowed for the first letter of property names. The contents of arrays and lists are obtained by using square bracket notation, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -684,13 +652,11 @@ shows: String invention = parser.parseExpression("Members[0].Inventions[6]").getValue( context, ieee, String.class); ---- -==== The contents of maps are obtained by specifying the literal key value within the brackets. In the following example, because keys for the `Officers` map are strings, we can specify string literals: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -707,7 +673,6 @@ string literals: parser.parseExpression("Officers['advisors'][0].PlaceOfBirth.Country").setValue( societyContext, "Croatia"); ---- -==== @@ -716,7 +681,6 @@ string literals: You can directly express lists in an expression by using `{}` notation. -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -725,7 +689,6 @@ You can directly express lists in an expression by using `{}` notation. List listOfLists = (List) parser.parseExpression("{{'a','b'},{'x','y'}}").getValue(context); ---- -==== `{}` by itself means an empty list. For performance reasons, if the list is itself entirely composed of fixed literals, a constant list is created to represent the @@ -739,7 +702,6 @@ expression (rather than building a new list on each evaluation). You can also directly express maps in an expression by using `{key:value}` notation. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -748,7 +710,6 @@ following example shows how to do so: Map mapOfMaps = (Map) parser.parseExpression("{name:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}").getValue(context); ---- -==== `{:}` by itself means an empty map. For performance reasons, if the map is itself composed of fixed literals or other nested constant structures (lists or maps), a constant map is created @@ -763,7 +724,6 @@ is optional. The examples above do not use quoted keys. You can build arrays by using the familiar Java syntax, optionally supplying an initializer to have the array populated at construction time. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -775,7 +735,6 @@ to have the array populated at construction time. The following example shows ho // Multi dimensional array int[][] numbers3 = (int[][]) parser.parseExpression("new int[4][5]").getValue(context); ---- -==== You cannot currently supply an initializer when you construct multi-dimensional array. @@ -789,7 +748,6 @@ You can invoke methods by using typical Java programming syntax. You can also in on literals. Variable arguments are also supported. The following examples show how to invoke methods: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -800,7 +758,6 @@ invoke methods: boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue( societyContext, Boolean.class); ---- -==== @@ -822,7 +779,6 @@ The relational operators (equal, not equal, less than, less than or equal, great and greater than or equal) are supported by using standard operator notation. The following listing shows a few examples of operators: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -835,7 +791,6 @@ following listing shows a few examples of operators: // evaluates to true boolean trueValue = parser.parseExpression("'black' < 'block'").getValue(Boolean.class); ---- -==== [NOTE] ==== @@ -851,7 +806,6 @@ in favor of comparisons against zero (for example, `X > 0` or `X < 0`). In addition to the standard relational operators, SpEL supports the `instanceof` and regular expression-based `matches` operator. The following listing shows examples of both: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -867,7 +821,6 @@ expression-based `matches` operator. The following listing shows examples of bot boolean falseValue = parser.parseExpression( "'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class); ---- -==== CAUTION: Be careful with primitive types, as they are immediately boxed up to the wrapper type, so `1 instanceof T(int)` evaluates to `false` while `1 instanceof T(Integer)` @@ -901,7 +854,6 @@ SpEL supports the following logical operators: The following example shows how to use the logical operators -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -932,7 +884,6 @@ The following example shows how to use the logical operators String expression = "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')"; boolean falseValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class); ---- -==== [[expressions-operators-mathematical]] @@ -943,7 +894,6 @@ and division operators only on numbers. You can also use the modulus (%) and exponential power (^) operators. Standard operator precedence is enforced. The following example shows the mathematical operators in use: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -976,7 +926,6 @@ following example shows the mathematical operators in use: // Operator precedence int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class); // -21 ---- -==== [[expressions-assignment]] @@ -986,7 +935,6 @@ To setting a property, use the assignment operator (`=`). This is typically done within a call to `setValue` but can also be done inside a call to `getValue`. The following listing shows both ways to use the assignment operator: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -999,7 +947,6 @@ following listing shows both ways to use the assignment operator: String aleks = parser.parseExpression( "Name = 'Aleksandar Seovic'").getValue(context, inventor, String.class); ---- -==== @@ -1014,7 +961,6 @@ type). Static methods are invoked by using this operator as well. The fully qualified, but all other type references must be. The following example shows how to use the `T` operator: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1026,7 +972,6 @@ to use the `T` operator: "T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR") .getValue(Boolean.class); ---- -==== @@ -1037,7 +982,6 @@ You can invoke constructors by using the `new` operator. You should use the full for all but the primitive types (`int`, `float`, and so on) and String. The following example shows how to use the `new` operator to invoke constructors: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1050,7 +994,6 @@ example shows how to use the `new` operator to invoke constructors: "Members.add(new org.spring.samples.spel.inventor.Inventor( 'Albert Einstein', 'German'))").getValue(societyContext); ---- -==== @@ -1061,7 +1004,6 @@ You can reference variables in the expression by using the `#variableName` synta are set by using the `setVariable` method on `EvaluationContext` implementations. The following example shows how to use variables: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1073,7 +1015,6 @@ following example shows how to use variables: parser.parseExpression("Name = #newName").getValue(context, tesla); System.out.println(tesla.getName()) // "Mike Tesla" ---- -==== [[expressions-this-root]] @@ -1085,7 +1026,6 @@ defined and refers to the root context object. Although `#this` may vary as comp an expression are evaluated, `#root` always refers to the root. The following examples show how to use the `#this` and `#root` variables: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1103,7 +1043,6 @@ show how to use the `#this` and `#root` variables: List primesGreaterThanTen = (List) parser.parseExpression( "#primes.?[#this>10]").getValue(context); ---- -==== @@ -1114,7 +1053,6 @@ You can extend SpEL by registering user-defined functions that can be called wit expression string. The function is registered through the `EvaluationContext`. The following example shows how to register a user-defined function: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1123,11 +1061,9 @@ following example shows how to register a user-defined function: EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build(); context.setVariable("myFunction", method); ---- -==== For example, consider the following utility method that reverses a string: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1142,11 +1078,9 @@ For example, consider the following utility method that reverses a string: } } ---- -==== You can then register and use the preceding method, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1159,7 +1093,6 @@ You can then register and use the preceding method, as the following example sho String helloWorldReversed = parser.parseExpression( "#reverseString('hello')").getValue(context, String.class); ---- -==== @@ -1170,7 +1103,6 @@ If the evaluation context has been configured with a bean resolver, you can look up beans from an expression by using the `@` symbol. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1181,12 +1113,10 @@ to do so: // This will end up calling resolve(context,"something") on MyBeanResolver during evaluation Object bean = parser.parseExpression("@something").getValue(context); ---- -==== To access a factory bean itself, you should instead prefix the bean name with an `&` symbol. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1197,7 +1127,6 @@ The following example shows how to do so: // This will end up calling resolve(context,"&foo") on MyBeanResolver during evaluation Object bean = parser.parseExpression("&foo").getValue(context); ---- -==== @@ -1207,19 +1136,16 @@ The following example shows how to do so: You can use the ternary operator for performing if-then-else conditional logic inside the expression. The following listing shows a minimal example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- String falseString = parser.parseExpression( "false ? 'trueExp' : 'falseExp'").getValue(String.class); ---- -==== In this case, the boolean `false` results in returning the string value `'falseExp'`. A more realistic example follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1233,7 +1159,6 @@ realistic example follows: .getValue(societyContext, String.class); // queryResultString = "Nikola Tesla is a member of the IEEE Society" ---- -==== See the next section on the Elvis operator for an even shorter syntax for the ternary operator. @@ -1248,19 +1173,16 @@ http://www.groovy-lang.org/operators.html#_elvis_operator[Groovy] language. With the ternary operator syntax, you usually have to repeat a variable twice, as the following example shows: -==== [source,groovy,indent=0] [subs="verbatim,quotes"] ---- String name = "Elvis Presley"; String displayName = (name != null ? name : "Unknown"); ---- -==== Instead, you can use the Elvis operator (named for the resemblance to Elvis' hair style). The following example shows how to use the Elvis operator: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1269,11 +1191,9 @@ The following example shows how to use the Elvis operator: String name = parser.parseExpression("name?:'Unknown'").getValue(String.class); System.out.println(name); // 'Unknown' ---- -==== The following listing shows A more complex example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1288,14 +1208,12 @@ The following listing shows A more complex example: name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, tesla, String.class); System.out.println(name); // Elvis Presley ---- -==== [NOTE] ===== You can use the Elvis operator to apply default values in expressions. The folloiwng example shows how to use the Elvis operator in a `@Value` expression: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1303,11 +1221,9 @@ example shows how to use the Elvis operator in a `@Value` expression: ---- This will inject a system property `pop3.port` if it is defined or 25 if not. -==== ===== - [[expressions-operator-safe-navigation]] === Safe Navigation Operator @@ -1318,7 +1234,6 @@ it is not null before accessing methods or properties of the object. To avoid th safe navigation operator returns null instead of throwing an exception. The following example shows how to use the safe navigation operator: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1335,7 +1250,6 @@ example shows how to use the safe navigation operator: city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, tesla, String.class); System.out.println(city); // null - does not throw NullPointerException!!! ---- -==== @@ -1349,14 +1263,12 @@ Selection uses a syntax of `.?[selectionExpression]`. It filters the collection returns a new collection that contain a subset of the original elements. For example, selection lets us easily get a list of Serbian inventors, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- List list = (List) parser.parseExpression( "Members.?[Nationality == 'Serbian']").getValue(societyContext); ---- -==== Selection is possible upon both lists and maps. For a list, the selection criteria is evaluated against each individual list element. Against a map, the @@ -1367,13 +1279,11 @@ the selection. The following expression returns a new map that consists of those elements of the original map where the entry value is less than 27: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- Map newMap = parser.parseExpression("map.?[value<27]").getValue(); ---- -==== In addition to returning all the selected elements, you can retrieve only the first or the last value. To obtain the first entry matching the selection, the syntax is @@ -1391,14 +1301,12 @@ example, suppose we have a list of inventors but want the list of cities where they were born. Effectively, we want to evaluate 'placeOfBirth.city' for every entry in the inventor list. The following example uses projection to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- // returns ['Smiljan', 'Idvor' ] List placesOfBirth = (List)parser.parseExpression("Members.![placeOfBirth.city]"); ---- -==== You can also use a map to drive projection and, in this case, the projection expression is evaluated against each entry in the map (represented as a Java `Map.Entry`). The result @@ -1415,7 +1323,6 @@ Each evaluation block is delimited with prefix and suffix characters that you ca define. A common choice is to use `#{ }` as the delimiters, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1425,7 +1332,6 @@ shows: // evaluates to "random number is 0.7038186818312008" ---- -==== The string is evaluated by concatenating the literal text `'random number is '` with the result of evaluating the expression inside the `#{ }` delimiter (in this case, the result @@ -1434,7 +1340,6 @@ is of the type `ParserContext`. The `ParserContext` interface is used to influen the expression is parsed in order to support the expression templating functionality. The definition of `TemplateParserContext` follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1453,7 +1358,6 @@ The definition of `TemplateParserContext` follows: } } ---- -==== @@ -1464,7 +1368,6 @@ The definition of `TemplateParserContext` follows: This section lists the classes used in the examples throughout this chapter. .Inventor.java -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1538,10 +1441,8 @@ This section lists the classes used in the examples throughout this chapter. } } ---- -==== .PlaceOfBirth.java -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1579,10 +1480,8 @@ This section lists the classes used in the examples throughout this chapter. } ---- -==== .Society.java -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1627,4 +1526,3 @@ This section lists the classes used in the examples throughout this chapter. } ---- -==== diff --git a/src/docs/asciidoc/core/core-resources.adoc b/src/docs/asciidoc/core/core-resources.adoc index c88dd9cffd..97e1211f41 100644 --- a/src/docs/asciidoc/core/core-resources.adoc +++ b/src/docs/asciidoc/core/core-resources.adoc @@ -37,7 +37,6 @@ Spring's `Resource` interface is meant to be a more capable interface for abstra access to low-level resources. The following listing shows the `Resource` interface definition: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -59,13 +58,11 @@ definition: } ---- -==== As the definition of the `Resource` interface shows, it extends the `InputStreamSource` interface. The following listing shows the definition of the `InputStreamSource` interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -75,7 +72,6 @@ interface: } ---- -==== Some of the most important methods from the `Resource` interface are: @@ -227,7 +223,6 @@ The `ResourceLoader` interface is meant to be implemented by objects that can re (that is, load) `Resource` instances. The following listing shows the `ResourceLoader` interface definition: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -237,7 +232,6 @@ interface definition: } ---- -==== All application contexts implement the `ResourceLoader` interface. Therefore, all application contexts may be used to obtain `Resource` instances. @@ -247,13 +241,11 @@ specified doesn't have a specific prefix, you get back a `Resource` type that is appropriate to that particular application context. For example, assume the following snippet of code was executed against a `ClassPathXmlApplicationContext` instance: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- Resource template = ctx.getResource("some/resource/path/myTemplate.txt"); ---- -==== Against a `ClassPathXmlApplicationContext`, that code returns a `ClassPathResource`. If the same method were executed against a `FileSystemXmlApplicationContext` instance, it would return a @@ -267,19 +259,16 @@ On the other hand, you may also force `ClassPathResource` to be used, regardless application context type, by specifying the special `classpath:` prefix, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt"); ---- -==== Similarly, you can force a `UrlResource` to be used by specifying any of the standard `java.net.URL` prefixes. The following pair of examples use the `file` and `http` prefixes: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -291,7 +280,6 @@ prefixes: ---- Resource template = ctx.getResource("http://myhost.com/resource/path/myTemplate.txt"); ---- -==== The following table summarizes the strategy for converting `String` objects to `Resource` objects: @@ -327,7 +315,6 @@ The `ResourceLoaderAware` interface is a special marker interface that identifie that expect to be provided with a `ResourceLoader` reference. The following listing shows the definition of the `ResourceLoaderAware` interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -336,7 +323,6 @@ the definition of the `ResourceLoaderAware` interface: void setResourceLoader(ResourceLoader resourceLoader); } ---- -==== When a class implements `ResourceLoaderAware` and is deployed into an application context (as a Spring-managed bean), it is recognized as `ResourceLoaderAware` by the @@ -381,7 +367,6 @@ register and use a special JavaBeans `PropertyEditor`, which can convert `String to `Resource` objects. So, if `myBean` has a template property of type `Resource`, it can be configured with a simple string for that resource, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -389,7 +374,6 @@ be configured with a simple string for that resource, as the following example s ---- -==== Note that the resource path has no prefix. Consequently, because the application context itself is going to be used as the `ResourceLoader`, the resource itself is loaded through a @@ -400,7 +384,6 @@ If you need to force a specific `Resource` type to be used, you can use a prefix The following two examples show how to force a `ClassPathResource` and a `UrlResource` (the latter being used to access a filesystem file): -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -412,7 +395,6 @@ The following two examples show how to force a `ClassPathResource` and a ---- ---- -==== @@ -437,25 +419,21 @@ that path and used to load the bean definitions depends on and is appropriate to specific application context. For example, consider the following example, which creates a `ClassPathXmlApplicationContext`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml"); ---- -==== The bean definitions are loaded from the classpath, because a `ClassPathResource` is used. However, consider the following example, which creates a `FileSystemXmlApplicationContext`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- ApplicationContext ctx = new FileSystemXmlApplicationContext("conf/appContext.xml"); ---- -==== Now the bean definition is loaded from a filesystem location (in this case, relative to the current working directory). @@ -487,7 +465,6 @@ then derives the path information from the supplied class. Consider the following directory layout: -==== [literal] [subs="verbatim,quotes"] ---- @@ -497,19 +474,16 @@ com/ daos.xml MessengerService.class ---- -==== The following example shows how a `ClassPathXmlApplicationContext` instance composed of the beans defined in files named `services.xml` and `daos.xml` (which are on the classpath) can be instantiated: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- ApplicationContext ctx = new ClassPathXmlApplicationContext( new String[] {"services.xml", "daos.xml"}, MessengerService.class); ---- -==== See the {api-spring-framework}/jca/context/SpringContextResourceAdapter.html[`ClassPathXmlApplicationContext`] javadoc for details on the various constructors. @@ -542,7 +516,6 @@ a resource points to just one resource at a time. Path locations can contain Ant-style patterns, as the following example shows: -==== [literal] [subs="verbatim"] ---- @@ -551,7 +524,6 @@ com/mycompany/**/applicationContext.xml file:C:/some/path/*-context.xml classpath:com/mycompany/**/applicationContext.xml ---- -==== When the path location contains an Ant-style pattern, the resolver follows a more complex procedure to try to resolve the wildcard. It produces a `Resource` for the path up to the last non-wildcard segment and @@ -590,14 +562,12 @@ coming from jars be thoroughly tested in your specific environment before you re When constructing an XML-based application context, a location string may use the special `classpath*:` prefix, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml"); ---- -==== This special prefix specifies that all classpath resources that match the given name must be obtained (internally, this essentially happens through a call to @@ -655,13 +625,11 @@ Ant-style patterns with `classpath:` resources are not guaranteed to find matchi resources if the root package to search is available in multiple class path locations. Consider the following example of a resource location: -==== [literal] [subs="verbatim,quotes"] ---- com/mycompany/package1/service-context.xml ---- -==== Now consider an Ant-style path that someone might use to try to find that file: @@ -695,7 +663,6 @@ For backwards compatibility (historical) reasons however, this changes when the to treat all location paths as relative, whether they start with a leading slash or not. In practice, this means the following examples are equivalent: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -709,12 +676,10 @@ In practice, this means the following examples are equivalent: ApplicationContext ctx = new FileSystemXmlApplicationContext("/conf/context.xml"); ---- -==== The following examples are also equivalent (even though it would make sense for them to be different, as one case is relative and the other absolute): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -728,14 +693,12 @@ case is relative and the other absolute): FileSystemXmlApplicationContext ctx = ...; ctx.getResource("/some/resource/path/myTemplate.txt"); ---- -==== In practice, if you need true absolute filesystem paths, you should avoid using absolute paths with `FileSystemResource` or `FileSystemXmlApplicationContext` and force the use of a `UrlResource` by using the `file:` URL prefix. The following examples show how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -750,4 +713,3 @@ show how to do so: ApplicationContext ctx = new FileSystemXmlApplicationContext("file:///conf/context.xml"); ---- -==== diff --git a/src/docs/asciidoc/core/core-validation.adoc b/src/docs/asciidoc/core/core-validation.adoc index b83ce0acc2..9d7ed4e94e 100644 --- a/src/docs/asciidoc/core/core-validation.adoc +++ b/src/docs/asciidoc/core/core-validation.adoc @@ -53,7 +53,6 @@ validators can report validation failures to the `Errors` object. Consider the following example of a small data object: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -65,7 +64,6 @@ Consider the following example of a small data object: // the usual getters and setters... } ---- -==== The next example provides validation behavior for the `Person` class by implementing the following two methods of the `org.springframework.validation.Validator` interface: @@ -78,7 +76,6 @@ Implementing a `Validator` is fairly straightforward, especially when you know o `ValidationUtils` helper class that the Spring Framework also provides. The following example implements `Validator` for `Person` instances: -==== [source,java,indent=0] [subs="verbatim"] ---- @@ -102,7 +99,6 @@ example implements `Validator` for `Person` instances: } } ---- -==== The `static` `rejectIfEmpty(..)` method on the `ValidationUtils` class is used to reject the `name` property if it is `null` or the empty string. Have a look at the @@ -120,7 +116,6 @@ within the `AddressValidator` class without resorting to copy-and-paste, you can dependency-inject or instantiate an `AddressValidator` within your `CustomerValidator`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -160,7 +155,6 @@ as the following example shows: } } ---- -==== Validation errors are reported to the `Errors` object passed to the validator. In the case of Spring Web MVC, you can use the `` tag to inspect the error messages, but @@ -265,7 +259,6 @@ and their default implementations, you should skip ahead to the < ---- -==== The `PropertyEditor` implementation could look similar to the following: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -605,12 +584,10 @@ The `PropertyEditor` implementation could look similar to the following: } } ---- -==== Finally, the following example shows how to use `CustomEditorConfigurer` to register the new `PropertyEditor` with the `ApplicationContext`, which will then be able to use it as needed: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -622,7 +599,6 @@ Finally, the following example shows how to use `CustomEditorConfigurer` to regi ---- -==== [[beans-beans-conversion-customeditor-registration-per]] ===== Using `PropertyEditorRegistrar` @@ -643,7 +619,6 @@ instances for each bean creation attempt. The following example shows how to create your own `PropertyEditorRegistrar` implementation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -660,7 +635,6 @@ The following example shows how to create your own `PropertyEditorRegistrar` imp } } ---- -==== See also the `org.springframework.beans.support.ResourceEditorRegistrar` for an example `PropertyEditorRegistrar` implementation. Notice how in its implementation of the @@ -669,7 +643,6 @@ See also the `org.springframework.beans.support.ResourceEditorRegistrar` for an The next example shows how to configure a `CustomEditorConfigurer` and inject an instance of our `CustomPropertyEditorRegistrar` into it: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -684,7 +657,6 @@ The next example shows how to configure a `CustomEditorConfigurer` and inject an ---- -==== Finally (and in a bit of a departure from the focus of this chapter for those of you using <>), using `PropertyEditorRegistrars` in @@ -692,7 +664,6 @@ conjunction with data-binding `Controllers` (such as `SimpleFormController`) can convenient. The following example uses a `PropertyEditorRegistrar` in the implementation of an `initBinder(..)` method: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -712,7 +683,6 @@ implementation of an `initBinder(..)` method: // other methods to do with registering a User } ---- -==== This style of `PropertyEditor` registration can lead to concise code (the implementation of `initBinder(..)` is only one line long) and lets common `PropertyEditor` @@ -740,7 +710,6 @@ application where type conversion is needed. The SPI to implement type conversion logic is simple and strongly typed, as the following interface definition shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -751,7 +720,6 @@ interface definition shows: T convert(S source); } ---- -==== To create your own converter, implement the `Converter` interface and parameterize `S` as the type you are converting from and `T` as the type you are converting to. You can also transparently apply such a @@ -768,7 +736,6 @@ Several converter implementations are provided in the `core.convert.support` pac a convenience. These include converters from strings to numbers and other common types. The following listing shows the `StringToInteger` class, which is a typical `Converter` implementation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -781,7 +748,6 @@ The following listing shows the `StringToInteger` class, which is a typical `Con } } ---- -==== @@ -792,7 +758,6 @@ When you need to centralize the conversion logic for an entire class hierarchy (for example, when converting from `String` to `Enum` objects), you can implement `ConverterFactory`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -803,7 +768,6 @@ When you need to centralize the conversion logic for an entire class hierarchy Converter getConverter(Class targetType); } ---- -==== Parameterize S to be the type you are converting from and R to be the base type defining the __range__ of classes you can convert to. Then implement `getConverter(Class)`, @@ -811,7 +775,6 @@ where T is a subclass of R. Consider the `StringToEnumConverterFactory` as an example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -837,7 +800,6 @@ Consider the `StringToEnumConverterFactory` as an example: } } ---- -==== @@ -852,7 +814,6 @@ context that you can use when you implement your conversion logic. Such context type conversion be driven by a field annotation or by generic information declared on a field signature. The following listing shows the interface definition of `GenericConverter`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -865,7 +826,6 @@ field signature. The following listing shows the interface definition of `Generi Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType); } ---- -==== To implement a `GenericConverter`, have `getConvertibleTypes()` return the supported source->target type pairs. Then implement `convert(Object, TypeDescriptor, @@ -894,7 +854,6 @@ on the target field, or you might want to run a `Converter` only if a specific m `ConditionalGenericConverter` is the union of the `GenericConverter` and `ConditionalConverter` interfaces that lets you define such custom matching criteria: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -906,7 +865,6 @@ on the target field, or you might want to run a `Converter` only if a specific m public interface ConditionalGenericConverter extends GenericConverter, ConditionalConverter { } ---- -==== A good example of a `ConditionalGenericConverter` is an `EntityConverter` that converts between a persistent entity identifier and an entity reference. Such an `EntityConverter` @@ -922,7 +880,6 @@ might match only if the target entity type declares a static finder method (for `ConversionService` defines a unified API for executing type conversion logic at runtime. Converters are often executed behind the following facade interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -940,7 +897,6 @@ runtime. Converters are often executed behind the following facade interface: } ---- -==== Most `ConversionService` implementations also implement `ConverterRegistry`, which provides an SPI for registering converters. Internally, a `ConversionService` @@ -969,21 +925,18 @@ system is used. To register a default `ConversionService` with Spring, add the following bean definition with an `id` of `conversionService`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== A default `ConversionService` can convert between strings, numbers, enums, collections, maps, and other common types. To supplement or override the default converters with your own custom converters, set the `converters` property. Property values can implement any of the `Converter`, `ConverterFactory`, or `GenericConverter` interfaces. -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -996,7 +949,6 @@ any of the `Converter`, `ConverterFactory`, or `GenericConverter` interfaces. ---- -==== It is also common to use a `ConversionService` within a Spring MVC application. See <> in the Spring MVC chapter. @@ -1013,7 +965,6 @@ In certain situations, you may wish to apply formatting during conversion. See To work with a `ConversionService` instance programmatically, you can inject a reference to it like you would for any other bean. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1030,7 +981,6 @@ it like you would for any other bean. The following example shows how to do so: } } ---- -==== For most use cases, you can use the `convert` method that specifies the `targetType`, but it does not work with more complex types, such as a collection of a parameterized element. @@ -1040,7 +990,6 @@ you need to provide a formal definition of the source and target types. Fortunately, `TypeDescriptor` provides various options to make doing so straightforward, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1051,7 +1000,6 @@ as the following example shows: TypeDescriptor.forObject(input), // List type descriptor TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(String.class))); ---- -==== Note that `DefaultConversionService` automatically registers converters that are appropriate for most environments. This includes collection converters, scalar @@ -1100,7 +1048,6 @@ provides a unified type conversion API for both SPIs. The `Formatter` SPI to implement field formatting logic is simple and strongly typed. The following listing shows the `Formatter` interface definition: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1109,12 +1056,10 @@ following listing shows the `Formatter` interface definition: public interface Formatter extends Printer, Parser { } ---- -==== `Formatter` extends from the `Printer` and `Parser` building-block interfaces. The following listing shows the definitions of those two interfaces: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1134,7 +1079,6 @@ following listing shows the definitions of those two interfaces: T parse(String clientValue, Locale locale) throws ParseException; } ---- -==== To create your own `Formatter`, implement the `Formatter` interface shown earlier. Parameterize `T` to be the type of object you wish to format -- for example, @@ -1153,7 +1097,6 @@ formatting support based on the http://joda-time.sourceforge.net[Joda-Time libra The following `DateFormatter` is an example `Formatter` implementation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1188,7 +1131,6 @@ The following `DateFormatter` is an example `Formatter` implementation: } } ---- -==== The Spring team welcomes community-driven `Formatter` contributionsSee https://jira.spring.io/browse/SPR[jira.spring.io] to contribute. @@ -1202,7 +1144,6 @@ Field formatting can be configured by field type or annotation. To bind an annotation to a `Formatter`, implement `AnnotationFormatterFactory`. The following listing shows the definition of the `AnnotationFormatterFactory` interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1217,7 +1158,6 @@ listing shows the definition of the `AnnotationFormatterFactory` interface: Parser getParser(A annotation, Class fieldType); } ---- -==== To create an implementation: . Parameterize A to be the field `annotationType` with which you wish to associate @@ -1230,7 +1170,6 @@ The following example `AnnotationFormatterFactory` implementation binds the `@Nu annotation to a formatter to let a number style or pattern be specified: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1267,12 +1206,10 @@ specified: } } ---- -==== To trigger formatting, you can annotate fields with @NumberFormat, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1282,7 +1219,6 @@ example shows: private BigDecimal decimal; } ---- -==== @@ -1297,7 +1233,6 @@ package. You can use `@NumberFormat` to format `Number` fields such as `Double` The following example uses `@DateTimeFormat` to format a `java.util.Date` as an ISO Date (yyyy-MM-dd): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1307,7 +1242,6 @@ The following example uses `@DateTimeFormat` to format a `java.util.Date` as an private Date date; } ---- -==== @@ -1323,7 +1257,6 @@ for use with Spring's `DataBinder` and the Spring Expression Language (SpEL). The following listing shows the `FormatterRegistry` SPI: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1340,7 +1273,6 @@ The following listing shows the `FormatterRegistry` SPI: void addFormatterForAnnotation(AnnotationFormatterFactory factory); } ---- -==== As shown in the preceding listing, you can register formatters by field type or by annotation. @@ -1358,7 +1290,6 @@ these rules once, and they are applied whenever formatting is needed. `FormatterRegistrar` is an SPI for registering formatters and converters through the FormatterRegistry. The following listing shows its interface definition: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1369,7 +1300,6 @@ FormatterRegistry. The following listing shows its interface definition: void registerFormatters(FormatterRegistry registry); } ---- -==== A `FormatterRegistrar` is useful when registering multiple related converters and formatters for a given formatting category, such as date formatting. It can also be @@ -1404,7 +1334,6 @@ you use the Joda-Time library. For example, the following Java configuration registers a global `yyyyMMdd` format (this example does not depend on the Joda-Time library): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1429,13 +1358,11 @@ format (this example does not depend on the Joda-Time library): } } ---- -==== If you prefer XML-based configuration, you can use a `FormattingConversionServiceFactoryBean`. The following example shows how to do so (this time using Joda Time): -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1467,7 +1394,6 @@ Time): ---- -==== NOTE: Joda-Time provides separate distinct types to represent `date`, `time`, and `date-time` values. The `dateFormatter`, `timeFormatter`, and `dateTimeFormatter` properties of the @@ -1504,7 +1430,6 @@ constraints. You can also define your own custom constraints. Consider the following example, which shows a simple `PersonForm` model with two properties: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1513,12 +1438,10 @@ Consider the following example, which shows a simple `PersonForm` model with two private int age; } ---- -==== JSR-303 lets you define declarative validation constraints against such properties, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1532,7 +1455,6 @@ following example shows: private int age; } ---- -==== When a JSR-303 Validator validates an instance of this class, these constraints are enforced. @@ -1556,14 +1478,12 @@ wherever validation is needed in your application. You can use the `LocalValidatorFactoryBean` to configure a default Validator as a Spring bean, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== The basic configuration in the preceding example triggers bean validation to initialize by using its default bootstrap mechanism. A JSR-303 or JSR-349 provider, such as the Hibernate Validator, @@ -1581,7 +1501,6 @@ these interfaces into beans that need to invoke validation logic. You can inject a reference to `javax.validation.Validator` if you prefer to work with the Bean Validation API directly, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1593,12 +1512,10 @@ Validation API directly, as the following example shows: @Autowired private Validator validator; ---- -==== You can inject a reference to `org.springframework.validation.Validator` if your bean requires the Spring Validation API, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1611,7 +1528,6 @@ the Spring Validation API, as the following example shows: private Validator validator; } ---- -==== [[validation-beanvalidation-spring-constraints]] @@ -1636,7 +1552,6 @@ that uses Spring to create `ConstraintValidator` instances. This lets your custo The following example shows a custom `@Constraint` declaration followed by an associated `ConstraintValidator` implementation that uses Spring for dependency injection: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1660,7 +1575,6 @@ The following example shows a custom `@Constraint` declaration followed by an as ... } ---- -==== As the preceding example shows, a `ConstraintValidator` implementation can have its dependencies `@Autowired` as any other Spring bean. @@ -1673,13 +1587,11 @@ You can integrate the method validation feature supported by Bean Validation 1.1 extension, also by Hibernate Validator 4.3) into a Spring context through a `MethodValidationPostProcessor` bean definition, as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== To be eligible for Spring-driven method validation, all target classes need to be annotated with Spring's `@Validated` annotation. (Optionally, you can also declare the validation groups to use.) @@ -1708,7 +1620,6 @@ configured, you can invoke the `Validator` by calling `binder.validate()`. Any v The following example shows how to use a `DataBinder` programmatically to invoke validation logic after binding to a target object: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1725,7 +1636,6 @@ logic after binding to a target object: // get BindingResult that includes any validation errors BindingResult results = binder.getBindingResult(); ---- -==== You can also configure a `DataBinder` with multiple `Validator` instances through `dataBinder.addValidators` and `dataBinder.replaceValidators`. This is useful when diff --git a/src/docs/asciidoc/data-access-appendix.adoc b/src/docs/asciidoc/data-access-appendix.adoc index f9aaaff040..2bda12f8e1 100644 --- a/src/docs/asciidoc/data-access-appendix.adoc +++ b/src/docs/asciidoc/data-access-appendix.adoc @@ -32,7 +32,6 @@ the following preamble at the top of your Spring XML configuration file. The tex following snippet references the correct schema so that the tags in the `tx` namespace are available to you: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -52,7 +51,6 @@ are available to you: ---- <1> Declare usage of the `tx` namespace. <2> Specify the location (with other schema locations). -==== NOTE: Often, when you use the elements in the `tx` namespace, you are also using the elements from the `aop` namespace (since the declarative transaction support in Spring is @@ -74,7 +72,6 @@ To use the elements in the `jdbc` schema, you need to have the following preambl top of your Spring XML configuration file. The text in the following snippet references the correct schema so that the elements in the `jdbc` namespace are available to you: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -92,4 +89,3 @@ the correct schema so that the elements in the `jdbc` namespace are available to ---- <1> Declare usage of the `jdbc` namespace. <2> Specify the location (with other schema locations). -==== diff --git a/src/docs/asciidoc/data-access.adoc b/src/docs/asciidoc/data-access.adoc index b11dcd2dac..4b02f3e9c2 100644 --- a/src/docs/asciidoc/data-access.adoc +++ b/src/docs/asciidoc/data-access.adoc @@ -153,7 +153,6 @@ The key to the Spring transaction abstraction is the notion of a transaction strategy. A transaction strategy is defined by the `org.springframework.transaction.PlatformTransactionManager` interface, which the following listing shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -166,7 +165,6 @@ strategy. A transaction strategy is defined by the void rollback(TransactionStatus status) throws TransactionException; } ---- -==== This is primarily a service provider interface (SPI), although you can use it <> from your application code. Because @@ -220,7 +218,6 @@ control transaction execution and query transaction status. The concepts should familiar, as they are common to all transaction APIs. The following listing shows the `TransactionStatus` interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -240,7 +237,6 @@ familiar, as they are common to all transaction APIs. The following listing show } ---- -==== Regardless of whether you opt for declarative or programmatic transaction management in Spring, defining the correct `PlatformTransactionManager` implementation is absolutely @@ -253,7 +249,6 @@ with plain JDBC.) You can define a JDBC `DataSource` by creating a bean similar to the following: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -264,12 +259,10 @@ You can define a JDBC `DataSource` by creating a bean similar to the following: ---- -==== The related `PlatformTransactionManager` bean definition then has a reference to the `DataSource` definition. It should resemble the following example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -277,13 +270,11 @@ the `DataSource` definition. It should resemble the following example: ---- -==== If you use JTA in a Java EE container, then you use a container `DataSource`, obtained through JNDI, in conjunction with Spring's `JtaTransactionManager`. The following example shows what the JTA and JNDI lookup version would look like: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -305,7 +296,6 @@ and JNDI lookup version would look like: ---- -==== The `JtaTransactionManager` does not need to know about the `DataSource` (or any other specific resources) because it uses the container's global transaction management @@ -331,7 +321,6 @@ same way as the `DataSourceTransactionManager` needs a reference to the `DataSou the `HibernateTransactionManager` needs a reference to the `SessionFactory`. The following example declares `sessionFactory` and `txManager` beans: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -353,7 +342,6 @@ The following example declares `sessionFactory` and `txManager` beans: ---- -==== If you use Hibernate and Java EE container-managed JTA transactions, you should use the same `JtaTransactionManager` as in the previous JTA example for @@ -417,13 +405,11 @@ For example, in the case of JDBC, instead of the traditional JDBC approach of ca the `getConnection()` method on the `DataSource`, you can instead use Spring's `org.springframework.jdbc.datasource.DataSourceUtils` class, as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- Connection conn = DataSourceUtils.getConnection(dataSource); ---- -==== If an existing transaction already has a connection synchronized (linked) to it, that instance is returned. Otherwise, the method call triggers the creation of a new @@ -560,7 +546,6 @@ instances in the body of each implemented method is good. That behavior lets you transactions be created and then rolled back in response to the `UnsupportedOperationException` instance. The following listing shows the `FooService` interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -580,11 +565,9 @@ transactions be created and then rolled back in response to the } ---- -==== The following example shows an implementation of the preceding interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -610,7 +593,6 @@ The following example shows an implementation of the preceding interface: } ---- -==== Assume that the first two methods of the `FooService` interface, `getFoo(String)` and `getFoo(String, String)`, must execute in the context of a transaction with read-only @@ -618,7 +600,6 @@ semantics, and that the other methods, `insertFoo(Foo)` and `updateFoo(Foo)`, mu execute in the context of a transaction with read-write semantics. The following configuration is explained in detail in the next few paragraphs: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -674,7 +655,6 @@ configuration is explained in detail in the next few paragraphs: ---- -==== Examine the preceding configuration. It assumes that you want to make a service object, the `fooService` bean, transactional. The transaction semantics to apply are encapsulated in the @@ -705,7 +685,6 @@ A common requirement is to make an entire service layer transactional. The best do this is to change the pointcut expression to match any operation in your service layer. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -714,7 +693,6 @@ service layer. The following example shows how to do so: ---- -==== NOTE: In the preceding example, it is assumed that all your service interfaces are defined in the `x.y.service` package. See <> for more details. @@ -729,7 +707,6 @@ proxy, a transaction is started, suspended, marked as read-only, and so on, depe on the transaction configuration associated with that method. Consider the following program that test drives the configuration shown earlier: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -742,13 +719,11 @@ program that test drives the configuration shown earlier: } } ---- -==== The output from running the preceding program should resemble the following (the Log4J output and the stack trace from the UnsupportedOperationException thrown by the insertFoo(..) method of the DefaultFooService class have been truncated for clarity): -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -779,7 +754,6 @@ insertFoo(..) method of the DefaultFooService class have been truncated for clar at $Proxy0.insertFoo(Unknown Source) at Boot.main(Boot.java:11) ---- -==== [[transaction-declarative-rolling-back]] @@ -807,7 +781,6 @@ You can configure exactly which `Exception` types mark a transaction for rollbac including checked exceptions. The following XML snippet demonstrates how you configure rollback for a checked, application-specific `Exception` type: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -818,14 +791,12 @@ rollback for a checked, application-specific `Exception` type: ---- -==== If you do not want a transaction rolled back when an exception is thrown, you can also specify 'no rollback rules'. The following example tells the Spring Framework's transaction infrastructure to commit the attendant transaction even in the face of an unhandled `InstrumentNotFoundException`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -836,7 +807,6 @@ unhandled `InstrumentNotFoundException`: ---- -==== When the Spring Framework's transaction infrastructure catches an exception and it consults the configured rollback rules to determine whether to mark the transaction for @@ -844,7 +814,6 @@ rollback, the strongest matching rule wins. So, in the case of the following configuration, any exception other than an `InstrumentNotFoundException` results in a rollback of the attendant transaction: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -854,14 +823,12 @@ rollback of the attendant transaction: ---- -==== You can also indicate a required rollback programmatically. Although simple, this process is quite invasive and tightly couples your code to the Spring Framework's transaction infrastructure. The following example shows how to programmatically indicate a required rollback: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -874,7 +841,6 @@ a required rollback: } } ---- -==== You are strongly encouraged to use the declarative approach to rollback, if at all possible. Programmatic rollback is available should you absolutely need it, but its @@ -894,7 +860,6 @@ defined in a root `x.y.service` package. To make all beans that are instances of defined in that package (or in subpackages) and that have names ending in `Service` have the default transactional configuration, you could write the following: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -939,12 +904,10 @@ the default transactional configuration, you could write the following: ---- -==== The following example shows how to configure two distinct beans with totally different transactional settings: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -998,7 +961,6 @@ transactional settings: ---- -==== [[transaction-declarative-txadvice-settings]] @@ -1081,7 +1043,6 @@ The ease-of-use afforded by the use of the `@Transactional` annotation is best illustrated with an example, which is explained in the text that follows. Consider the following class definition: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1098,7 +1059,6 @@ Consider the following class definition: void updateFoo(Foo foo); } ---- -==== Used at the class level as above, the annotation indicates a default for all methods of the declaring class (as well as its subclasses). Alternatively, each method can @@ -1114,7 +1074,6 @@ for full details. In XML configuration, the `` tag provides similar convenience: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1148,7 +1107,7 @@ In XML configuration, the `` tag provides similar conveni ---- <1> The line that makes the bean instance transactional. -==== + TIP: You can omit the `transaction-manager` attribute in the `` tag if the bean name of the `PlatformTransactionManager` that you want to wire in has the name, @@ -1261,7 +1220,6 @@ annotated at the class level with the settings for a read-only transaction, but `@Transactional` annotation on the `updateFoo(Foo)` method in the same class takes precedence over the transactional settings defined at the class level. -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1279,7 +1237,6 @@ precedence over the transactional settings defined at the class level. } } ---- -==== [[transaction-declarative-attransactional-settings]] ===== `@Transactional` Settings @@ -1360,7 +1317,6 @@ This can either be the bean name or the qualifier value of the transaction manag For example, using the qualifier notation, you can combine the following Java code with the following transaction manager bean declarations in the application context: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1373,11 +1329,9 @@ the following transaction manager bean declarations in the application context: public void doSomething() { ... } } ---- -==== The following listing shows the bean declarations: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1393,7 +1347,6 @@ The following listing shows the bean declarations: ---- -==== In this case, the two methods on `TransactionalService` run under separate transaction managers, differentiated by the `order` and `account` qualifiers. The default @@ -1408,7 +1361,6 @@ methods, <> l define custom shortcut annotations for your specific use cases. For example, consider the following annotation definitions: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1424,11 +1376,9 @@ following annotation definitions: public @interface AccountTx { } ---- -==== The preceding annotations lets us write the example from the previous section as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1441,7 +1391,6 @@ The preceding annotations lets us write the example from the previous section as public void doSomething() { ... } } ---- -==== In the preceding example, we used the syntax to define the transaction manager qualifier, but we could also have included propagation behavior, rollback rules, timeouts, and other features. @@ -1584,7 +1533,6 @@ is controlled through the `Ordered` interface. For full details on advice orderi The following configuration creates a `fooService` bean that has profiling and transactional aspects applied to it in the desired order: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -1633,7 +1581,6 @@ transactional aspects applied to it in the desired order: ---- -==== You can configure any number of additional aspects in similar fashion. @@ -1641,7 +1588,6 @@ of additional aspects in similar fashion. The following example creates the same setup as the previous two examples but uses the purely XML declarative approach: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -1692,7 +1638,6 @@ declarative approach: ---- -==== The result of the preceding configuration is a `fooService` bean that has profiling and transactional aspects applied to it in that order. If you want the profiling advice @@ -1726,7 +1671,6 @@ NOTE: Prior to continuing, you may want to read < " ---- -==== You can then inject the `sharedTransactionTemplate` into as many services as are required. @@ -1920,7 +1853,6 @@ directly to manage your transaction. To do so, pass the implementation of the by using the `TransactionDefinition` and `TransactionStatus` objects, you can initiate transactions, roll back, and commit. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1939,7 +1871,6 @@ transactions, roll back, and commit. The following example shows how to do so: } txManager.commit(status); ---- -==== @@ -1979,7 +1910,6 @@ event and that we want to define a listener that should only handle that event o transaction in which it has been published has committed successfully. The following example sets up such an event listener: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1992,7 +1922,6 @@ example sets up such an event listener: } } ---- -==== The `@TransactionalEventListener` annotation exposes a `phase` attribute that lets you customize the phase of the transaction to which the listener should be bound. The valid phases are `BEFORE_COMMIT`, @@ -2150,7 +2079,6 @@ lets the component scanning support find and configure your DAOs and repositorie without having to provide XML configuration entries for them. The following example shows how to use the `@Repository` annotation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2160,7 +2088,7 @@ how to use the `@Repository` annotation: } ---- <1> The `@Repository` annotation. -==== + Any DAO or repository implementation needs access to a persistence resource, depending on the persistence technology used. For example, a JDBC-based repository @@ -2169,7 +2097,6 @@ needs access to a JDBC `DataSource`, and a JPA-based repository needs access to injected by using one of the `@Autowired`, `@Inject`, `@Resource` or `@PersistenceContext` annotations. The following example works for a JPA repository: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2183,12 +2110,10 @@ annotations. The following example works for a JPA repository: } ---- -==== If you use the classic Hibernate APIs, you can inject `SessionFactory`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2206,14 +2131,12 @@ example shows: } ---- -==== The last example we show here is for typical JDBC support. You could have the `DataSource` injected into an initialization method, where you would create a `JdbcTemplate` and other data access support classes (such as `SimpleJdbcCall` and others) by using this `DataSource`. The following example autowires a `DataSource`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2231,7 +2154,6 @@ this `DataSource`. The following example autowires a `DataSource`: } ---- -==== NOTE: See the specific coverage of each persistence technology for details on how to configure the application context to take advantage of these annotations. @@ -2422,28 +2344,23 @@ See the attendant {api-spring-framework}/jdbc/core/JdbcTemplate.html[javadoc] fo The following query gets the number of rows in a relation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- int rowCount = this.jdbcTemplate.queryForObject("select count(*) from t_actor", Integer.class); ---- -==== The following query uses a bind variable: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- int countOfActorsNamedJoe = this.jdbcTemplate.queryForObject( "select count(*) from t_actor where first_name = ?", Integer.class, "Joe"); ---- -==== The following query looks for a `String`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2451,11 +2368,9 @@ The following query looks for a `String`: "select last_name from t_actor where id = ?", new Object[]{1212L}, String.class); ---- -==== The following query finds and populates a single domain object: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2471,11 +2386,9 @@ The following query finds and populates a single domain object: } }); ---- -==== The following query finds and populates a number of domain objects: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2490,7 +2403,6 @@ The following query finds and populates a number of domain objects: } }); ---- -==== If the last two snippets of code actually existed in the same application, it would make sense to remove the duplication present in the two `RowMapper` anonymous inner classes @@ -2498,7 +2410,6 @@ and extract them out into a single class (typically a `static` nested class) tha then be referenced by DAO methods as needed. For example, it may be better to write the preceding code snippet as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2516,7 +2427,6 @@ preceding code snippet as follows: } } ---- -==== [[jdbc-JdbcTemplate-examples-update]] ===== Updating (`INSERT`, `UPDATE`, and `DELETE`) with `JdbcTemplate` @@ -2526,7 +2436,6 @@ Parameter values are usually provided as variable arguments or, alternatively, a The following example inserts a new entry: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2534,11 +2443,9 @@ The following example inserts a new entry: "insert into t_actor (first_name, last_name) values (?, ?)", "Leonor", "Watling"); ---- -==== The following example updates an existing entry: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2546,11 +2453,9 @@ The following example updates an existing entry: "update t_actor set last_name = ? where id = ?", "Banjo", 5276L); ---- -==== The following example deletes an entry: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2558,7 +2463,6 @@ The following example deletes an entry: "delete from actor where id = ?", Long.valueOf(actorId)); ---- -==== [[jdbc-JdbcTemplate-examples-other]] ===== Other `JdbcTemplate` Operations @@ -2568,17 +2472,14 @@ method is often used for DDL statements. It is heavily overloaded with variants callback interfaces, binding variable arrays, and so on. The following example creates a table: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- this.jdbcTemplate.execute("create table mytable (id integer, name varchar(100))"); ---- -==== The following example invokes a stored procedure: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2586,7 +2487,6 @@ The following example invokes a stored procedure: "call SUPPORT.REFRESH_ACTORS_SUMMARY(?)", Long.valueOf(unionId)); ---- -==== More sophisticated stored procedure support is <>. @@ -2605,7 +2505,6 @@ configure a `DataSource` in your Spring configuration file and then dependency-i that shared `DataSource` bean into your DAO classes. The `JdbcTemplate` is created in the setter for the `DataSource`. This leads to DAOs that resemble the following: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2620,11 +2519,9 @@ the setter for the `DataSource`. This leads to DAOs that resemble the following: // JDBC-backed implementations of the methods on the CorporateEventDao follow... } ---- -==== The following example shows the corresponding XML configuration: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2653,14 +2550,12 @@ The following example shows the corresponding XML configuration: ---- -==== An alternative to explicit configuration is to use component-scanning and annotation support for dependency injection. In this case, you can annotate the class with `@Repository` (which makes it a candidate for component-scanning) and annotate the `DataSource` setter method with `@Autowired`. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2680,11 +2575,10 @@ method with `@Autowired`. The following example shows how to do so: <1> Annotate the class with `@Repository`. <2> annotate the `DataSource` setter method with `@Autowired`. <3> Create a new `JdbcTemplate` with the `DataSource`. -==== + The following example shows the corresponding XML configuration: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2712,7 +2606,6 @@ The following example shows the corresponding XML configuration: ---- -==== If you use Spring's `JdbcDaoSupport` class and your various JDBC-backed DAO classes extend from it, your sub-class inherits a `setDataSource(..)` method from the @@ -2738,7 +2631,6 @@ section describes only those areas of the `NamedParameterJdbcTemplate` class tha from the `JdbcTemplate` itself -- namely, programming JDBC statements by using named parameters. The following example shows how to use `NamedParameterJdbcTemplate`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2758,7 +2650,6 @@ parameters. The following example shows how to use `NamedParameterJdbcTemplate`: return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class); } ---- -==== Notice the use of the named parameter notation in the value assigned to the `sql` variable and the corresponding value that is plugged into the `namedParameters` @@ -2771,7 +2662,6 @@ methods exposed by the `NamedParameterJdbcOperations` and implemented by the The following example shows the use of the `Map`-based style: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2791,7 +2681,6 @@ The following example shows the use of the `Map`-based style: return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class); } ---- -==== One nice feature related to the `NamedParameterJdbcTemplate` (and existing in the same Java package) is the `SqlParameterSource` interface. You have already seen an example of @@ -2809,7 +2698,6 @@ of named parameter values. The following example shows a typical JavaBean: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2835,12 +2723,10 @@ The following example shows a typical JavaBean: } ---- -==== The following example uses a `NamedParameterJdbcTemplate` to return the count of the members of the class shown in the preceding example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2861,7 +2747,6 @@ members of the class shown in the preceding example: return this.namedParameterJdbcTemplate.queryForObject(sql, namedParameters, Integer.class); } ---- -==== Remember that the `NamedParameterJdbcTemplate` class wraps a classic `JdbcTemplate` template. If you need access to the wrapped `JdbcTemplate` instance to access @@ -2913,7 +2798,6 @@ name from the database metadata of the database in use. You can extend `SQLErrorCodeSQLExceptionTranslator`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2927,7 +2811,6 @@ You can extend `SQLErrorCodeSQLExceptionTranslator`, as the following example sh } } ---- -==== In the preceding example, the specific error code (`-12345`) is translated, while other errors are left to be translated by the default translator implementation. To use this custom @@ -2936,7 +2819,6 @@ translator, you must pass it to the `JdbcTemplate` through the method processing where this translator is needed. The following example shows how you can use this custom translator: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2962,7 +2844,6 @@ translator: " where id = ?", pct, orderId); } ---- -==== The custom translator is passed a data source in order to look up the error codes in `sql-error-codes.xml`. @@ -2976,7 +2857,6 @@ Running an SQL statement requires very little code. You need a `DataSource` and `JdbcTemplate`. The following example shows what you need to include for a minimal but fully functional class that creates a new table: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2996,7 +2876,6 @@ fully functional class that creates a new table: } } ---- -==== [[jdbc-statements-querying]] @@ -3008,7 +2887,6 @@ Java class that is passed in as an argument. If the type conversion is invalid, `InvalidDataAccessApiUsageException` is thrown. The following example contains two query methods, one for an `int` and one that queries for a `String`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3032,7 +2910,6 @@ query methods, one for an `int` and one that queries for a `String`: } } ---- -==== In addition to the single result query methods, several methods return a list with an entry for each row that the query returned. The most generic method is `queryForList(..)`, @@ -3040,7 +2917,6 @@ which returns a `List` where each element is a `Map` containing one entry for ea using the column name as the key. If you add a method to the preceding example to retrieve a list of all the rows, it might be as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3054,17 +2930,14 @@ list of all the rows, it might be as follows: return this.jdbcTemplate.queryForList("select * from mytable"); } ---- -==== The returned list would resemble the following: -==== [literal] [subs="verbatim,quotes"] ---- [{name=Bob, id=1}, {name=Mary, id=2}] ---- -==== [[jdbc-updates]] @@ -3072,7 +2945,6 @@ The returned list would resemble the following: The following example updates a column for a certain primary key: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3092,7 +2964,6 @@ The following example updates a column for a certain primary key: } } ---- -==== In the preceding example, an SQL statement has placeholders for row parameters. You can pass the parameter values @@ -3112,7 +2983,6 @@ update. There is no standard single way to create an appropriate `PreparedStatem (which explains why the method signature is the way it is). The following example works on Oracle but may not work on other platforms: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3132,7 +3002,6 @@ on Oracle but may not work on other platforms: // keyHolder.getKey() now contains the generated key ---- -==== @@ -3186,7 +3055,6 @@ To configure a `DriverManagerDataSource`: The following example shows how to configure a `DriverManagerDataSource` in Java: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3196,11 +3064,9 @@ The following example shows how to configure a `DriverManagerDataSource` in Java dataSource.setUsername("sa"); dataSource.setPassword(""); ---- -==== The following example shows the corresponding XML configuration: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3213,7 +3079,6 @@ The following example shows the corresponding XML configuration: ---- -==== The next two examples show the basic connectivity and configuration for DBCP and C3P0. To learn about more options that help control the pooling features, see the product @@ -3221,7 +3086,6 @@ documentation for the respective connection pooling implementations. The following example shows DBCP configuration: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3234,11 +3098,9 @@ The following example shows DBCP configuration: ---- -==== The following example shows C3P0 configuration: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3251,7 +3113,6 @@ The following example shows C3P0 configuration: ---- -==== [[jdbc-DataSourceUtils]] @@ -3379,7 +3240,6 @@ the prepared statement. This method is called the number of times that you specified in the `getBatchSize` call. The following example updates the `actor` table based on entries in a list, and the entire list is used as the batch: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3409,7 +3269,6 @@ based on entries in a list, and the entire list is used as the batch: // ... additional methods } ---- -==== If you process a stream of updates or reading from a file, you might have a preferred batch size, but the last batch might not have that number of entries. In this @@ -3433,7 +3292,6 @@ in an array of bean-style objects (with getter methods corresponding to paramete The following example shows a batch update using named parameters: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3454,7 +3312,6 @@ The following example shows a batch update using named parameters: // ... additional methods } ---- -==== For an SQL statement that uses the classic `?` placeholders, you pass in a list containing an object array with the update values. This object array must have one entry @@ -3464,7 +3321,6 @@ defined in the SQL statement. The following example is the same as the preceding example, except that it uses classic JDBC `?` placeholders: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3491,7 +3347,6 @@ JDBC `?` placeholders: // ... additional methods } ---- -==== All of the batch update methods that we described earlier return an `int` array containing the number of affected rows for each batch entry. This count is reported by @@ -3530,7 +3385,6 @@ update calls into batches of the size specified. The following example shows a batch update that uses a batch size of 100: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3560,7 +3414,6 @@ The following example shows a batch update that uses a batch size of 100: // ... additional methods } ---- -==== The batch update methods for this call returns an array of `int` arrays that contain an array entry for each batch with an array of the number of affected rows for each update. The top @@ -3594,7 +3447,6 @@ Configuration methods for this class follow the `fluid` style that returns the i of the `SimpleJdbcInsert`, which lets you chain all configuration methods. The following example uses only one configuration method (we show examples of multiple methods later): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3619,7 +3471,6 @@ example uses only one configuration method (we show examples of multiple methods // ... additional methods } ---- -==== The `execute` method used here takes a plain `java.util.Map` as its only parameter. The important thing to note here is that the keys used for the `Map` must match the column @@ -3636,7 +3487,6 @@ the `SimpleJdbcInsert`, in addition to specifying the table name, it specifies t of the generated key column with the `usingGeneratedKeyColumns` method. The following listing shows how it works: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3663,7 +3513,6 @@ listing shows how it works: // ... additional methods } ---- -==== The main difference when you run the insert by using this second approach is that you do not add the `id` to the `Map`, and you call the `executeAndReturnKey` method. This returns a @@ -3680,7 +3529,6 @@ use a `KeyHolder` that is returned from the `executeAndReturnKeyHolder` method. You can limit the columns for an insert by specifying a list of column names with the `usingColumns` method, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3708,7 +3556,6 @@ You can limit the columns for an insert by specifying a list of column names wit // ... additional methods } ---- -==== The execution of the insert is the same as if you had relied on the metadata to determine which columns to use. @@ -3724,7 +3571,6 @@ which is a very convenient class if you have a JavaBean-compliant class that con your values. It uses the corresponding getter method to extract the parameter values. The following example shows how to use `BeanPropertySqlParameterSource`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3749,12 +3595,10 @@ values. The following example shows how to use `BeanPropertySqlParameterSource`: // ... additional methods } ---- -==== Another option is the `MapSqlParameterSource` that resembles a `Map` but provides a more convenient `addValue` method that can be chained. The following example shows how to use it: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3781,7 +3625,6 @@ convenient `addValue` method that can be chained. The following example shows ho // ... additional methods } ---- -==== As you can see, the configuration is the same. Only the executing code has to change to use these alternative input classes. @@ -3799,7 +3642,6 @@ from a MySQL database. The example procedure reads a specified actor entry and r `first_name`, `last_name`, and `birth_date` columns in the form of `out` parameters. The following listing shows the first example: -==== [source,sql,indent=0] [subs="verbatim,quotes"] ---- @@ -3814,7 +3656,6 @@ The following listing shows the first example: FROM t_actor where id = in_id; END; ---- -==== The `in_id` parameter contains the `id` of the actor that you are looking up. The `out` parameters return the data read from the table. @@ -3827,7 +3668,6 @@ The following example of a `SimpleJdbcCall` configuration uses the preceding sto procedure (the only configuration option, in addition to the `DataSource`, is the name of the stored procedure): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3857,7 +3697,6 @@ of the stored procedure): // ... additional methods } ---- -==== The code you write for the execution of the call involves creating an `SqlParameterSource` containing the IN parameter. You must match the name provided for the input value @@ -3881,7 +3720,6 @@ To do the latter, you can create your own `JdbcTemplate` and set the `setResults property to `true`. Then you can pass this customized `JdbcTemplate` instance into the constructor of your `SimpleJdbcCall`. The following example shows this configuration: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3899,7 +3737,6 @@ the constructor of your `SimpleJdbcCall`. The following example shows this confi // ... additional methods } ---- -==== By taking this action, you avoid conflicts in the case used for the names of your returned `out` parameters. @@ -3930,7 +3767,6 @@ of IN parameter names to include for a given signature. The following example shows a fully declared procedure call and uses the information from the preceding example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3956,7 +3792,6 @@ the preceding example: // ... additional methods } ---- -==== The execution and end results of the two examples are the same. The second example specifies all details explicitly rather than relying on metadata. @@ -3971,14 +3806,12 @@ To do so, you typically specify the parameter name and SQL type in the construct is specified by using the `java.sql.Types` constants. Earlier in this chapter, we saw declarations similar to the following: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- new SqlParameter("in_id", Types.NUMERIC), new SqlOutParameter("out_first_name", Types.VARCHAR), ---- -==== The first line with the `SqlParameter` declares an IN parameter. You can use IN parameters for both stored procedure calls and for queries by using the `SqlQuery` and its @@ -4014,7 +3847,6 @@ not have to retrieve the return value from the results map. A similar convenienc parameter. The following example (for MySQL) is based on a stored function named `get_actor_name` that returns an actor's full name: -==== [source,sql,indent=0] [subs="verbatim,quotes"] ---- @@ -4028,12 +3860,10 @@ that returns an actor's full name: RETURN out_name; END; ---- -==== To call this function, we again create a `SimpleJdbcCall` in the initialization method, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4060,7 +3890,6 @@ as the following example shows: // ... additional methods } ---- -==== The `executeFunction` method used returns a `String` that contains the return value from the function call. @@ -4083,7 +3912,6 @@ in the results map that is returned from the `execute` statement. The next example (for MySQL) uses a stored procedure that takes no IN parameters and returns all rows from the `t_actor` table: -==== [source,sql,indent=0] [subs="verbatim,quotes"] ---- @@ -4092,14 +3920,12 @@ all rows from the `t_actor` table: SELECT a.id, a.first_name, a.last_name, a.birth_date FROM t_actor a; END; ---- -==== To call this procedure, you can declare the `RowMapper`. Because the class to which you want to map follows the JavaBean rules, you can use a `BeanPropertyRowMapper` that is created by passing in the required class to map to in the `newInstance` method. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4124,7 +3950,6 @@ The following example shows how to do so: // ... additional methods } ---- -==== The `execute` call passes in an empty `Map`, because this call does not take any parameters. The list of actors is then retrieved from the results map and returned to the caller. @@ -4173,7 +3998,6 @@ abstract `mapRow(..)` method to convert each row of the supplied `ResultSet` int object of the type specified. The following example shows a custom query that maps the data from the `t_actor` relation to an instance of the `Actor` class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4196,7 +4020,6 @@ data from the `t_actor` relation to an instance of the `Actor` class: } ---- -==== The class extends `MappingSqlQuery` parameterized with the `Actor` type. The constructor for this customer query takes a `DataSource` as the only parameter. In this @@ -4211,7 +4034,6 @@ thread-safe after it is compiled, so, as long as these instances are created whe is initialized, they can be kept as instance variables and be reused. The following example shows how to define such a class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4226,7 +4048,6 @@ example shows how to define such a class: return actorMappingQuery.findObject(id); } ---- -==== The method in the preceding example retrieves the customer with the `id` that is passed in as the only parameter. Since we want only one object to be returned, we call the `findObject` convenience @@ -4235,7 +4056,6 @@ list of objects and took additional parameters, we would use one of the `execute methods that takes an array of parameter values passed in as varargs. The following example shows such a method: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4244,7 +4064,6 @@ example shows such a method: return actors; } ---- -==== [[jdbc-SqlUpdate]] @@ -4259,7 +4078,6 @@ However, you do not have to subclass the `SqlUpdate` class, since it can easily be parameterized by setting SQL and declaring parameters. The following example creates a custom update method named `execute`: -==== [source,java,indent=0] [subs="verbatim"] ---- @@ -4288,7 +4106,6 @@ The following example creates a custom update method named `execute`: } } ---- -==== [[jdbc-StoredProcedure]] @@ -4305,14 +4122,12 @@ To define a parameter for the `StoredProcedure` class, you can use an `SqlParame of its subclasses. You must specify the parameter name and SQL type in the constructor, as the following code snippet shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- new SqlParameter("in_id", Types.NUMERIC), new SqlOutParameter("out_first_name", Types.VARCHAR), ---- -==== The SQL type is specified using the `java.sql.Types` constants. @@ -4341,7 +4156,6 @@ returned date from the results `Map`. The results `Map` has an entry for each de output parameter (in this case, only one) by using the parameter name as the key. The following listing shows our custom StoredProcedure class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4389,12 +4203,10 @@ The following listing shows our custom StoredProcedure class: } ---- -==== The following example of a `StoredProcedure` has two output parameters (in this case, Oracle REF cursors): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4422,7 +4234,6 @@ Oracle REF cursors): } } ---- -==== Notice how the overloaded variants of the `declareParameter(..)` method that have been used in the `TitlesAndGenresStoredProcedure` constructor are passed `RowMapper` @@ -4432,7 +4243,6 @@ functionality. The next two examples provide code for the two `RowMapper` implem The `TitleMapper` class maps a `ResultSet` to a `Title` domain object for each row in the supplied `ResultSet`, as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4451,12 +4261,10 @@ the supplied `ResultSet`, as follows: } } ---- -==== The `GenreMapper` class maps a `ResultSet` to a `Genre` domain object for each row in the supplied `ResultSet`, as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4472,13 +4280,11 @@ the supplied `ResultSet`, as follows: } } ---- -==== To pass parameters to a stored procedure that has one or more input parameters in its definition in the RDBMS, you can code a strongly typed `execute(..)` method that would delegate to the untyped `execute(Map)` method in the superclass, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4511,7 +4317,6 @@ delegate to the untyped `execute(Map)` method in the superclass, as the followin } } ---- -==== @@ -4580,7 +4385,6 @@ dependency injection. The following example shows how to create and insert a BLOB: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4608,7 +4412,7 @@ The following example shows how to create and insert a BLOB: <1> Pass in the `lobHandler` that (in this example) is a plain `DefaultLobHandler`. <2> Using the method `setClobAsCharacterStream` to pass in the contents of the CLOB. <3> Using the method `setBlobAsBinaryStream` to pass in the contents of the BLOB. -==== + [NOTE] ==== @@ -4627,7 +4431,6 @@ Now it is time to read the LOB data from the database. Again, you use a `JdbcTem with the same instance variable `lobHandler` and a reference to a `DefaultLobHandler`. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4646,7 +4449,6 @@ The following example shows how to do so: <1> Using the method `getClobAsString` to retrieve the contents of the CLOB. <2> Using the method `getBlobAsBytes` to retrieve the contents of the BLOB. -==== [[jdbc-in-clause]] @@ -4687,7 +4489,6 @@ The `SqlReturnType` interface has a single method (named declaration of an `SqlOutParameter`. The following example shows returning the value of an Oracle `STRUCT` object of the user declared type `ITEM_TYPE`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4710,7 +4511,6 @@ declared type `ITEM_TYPE`: ... } ---- -==== You can use `SqlTypeValue` to pass the value of a Java object (such as `TestItem`) to a stored procedure. The `SqlTypeValue` interface has a single method (named @@ -4718,7 +4518,6 @@ stored procedure. The `SqlTypeValue` interface has a single method (named can use it to create database-specific objects, such as `StructDescriptor` instances or `ArrayDescriptor` instances. The following example creates a `StructDescriptor` instance: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4738,7 +4537,6 @@ or `ArrayDescriptor` instances. The following example creates a `StructDescripto } }; ---- -==== You can now add this `SqlTypeValue` to the `Map` that contains the input parameters for the `execute` call of the stored procedure. @@ -4748,7 +4546,6 @@ procedure. Oracle has its own internal `ARRAY` class that must be used in this c you can use the `SqlTypeValue` to create an instance of the Oracle `ARRAY` and populate it with values from the Java `ARRAY`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4762,7 +4559,6 @@ it with values from the Java `ARRAY`, as the following example shows: } }; ---- -==== @@ -4790,7 +4586,6 @@ testability, and the ability to rapidly evolve your SQL during development. If you want to expose an embedded database instance as a bean in a Spring `ApplicationContext`, you can use the `embedded-database` tag in the `spring-jdbc` namespace: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4799,7 +4594,6 @@ If you want to expose an embedded database instance as a bean in a Spring ---- -==== The preceding configuration creates an embedded HSQL database that is populated with SQL from the `schema.sql` and `test-data.sql` resources in the root of the classpath. In addition, as @@ -4815,7 +4609,6 @@ The `EmbeddedDatabaseBuilder` class provides a fluent API for constructing an em database programmatically. You can use this when you need to create an embedded database in a stand-alone environment or in a stand-alone integration test, as in the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4832,7 +4625,6 @@ EmbeddedDatabase db = new EmbeddedDatabaseBuilder() db.shutdown() ---- -==== See the {api-spring-framework}/jdbc/datasource/embedded/EmbeddedDatabaseBuilder.html[javadoc for `EmbeddedDatabaseBuilder`] for further details on all supported options. @@ -4840,7 +4632,6 @@ for further details on all supported options. You can also use the `EmbeddedDatabaseBuilder` to create an embedded database by using Java configuration, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4860,7 +4651,6 @@ public class DataSourceConfig { } } ---- -==== [[jdbc-embedded-database-types]] @@ -4908,7 +4698,6 @@ Framework>> and configuring the embedded database as a bean in the Spring `ApplicationContext` as described in <> and <>. The following listing shows the test template: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4939,7 +4728,6 @@ Framework>> and configuring the embedded database as a bean in the Spring } ---- -==== [[jdbc-embedded-database-unique-names]] @@ -5002,7 +4790,6 @@ an instance that runs on a server somewhere. If you want to initialize a database and you can provide a reference to a `DataSource` bean, you can use the `initialize-database` tag in the `spring-jdbc` namespace: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5011,7 +4798,6 @@ bean, you can use the `initialize-database` tag in the `spring-jdbc` namespace: ---- -==== The preceding example runs the two specified scripts against the database. The first script creates a schema, and the second populates tables with a test data set. The script @@ -5032,7 +4818,6 @@ namespace provides a few additional options. The first is a flag to switch the initialization on and off. You can set this according to the environment (such as pulling a boolean value from system properties or from an environment bean). The following example gets a value from a system property: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5042,13 +4827,12 @@ boolean value from system properties or from an environment bean). The following ---- <1> Get the value for `enabled` from a system property called `INITIALIZE_DATABASE`. -==== + The second option to control what happens with existing data is to be more tolerant of failures. To this end, you can control the ability of the initializer to ignore certain errors in the SQL it executes from the scripts, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5056,7 +4840,6 @@ errors in the SQL it executes from the scripts, as the following example shows: ---- -==== In the preceding example, we are saying that we expect that, sometimes, the scripts are run against an empty database, and there are some `DROP` statements in the scripts that @@ -5073,7 +4856,6 @@ Each statement should be separated by `;` or a new line if the `;` character is present at all in the script. You can control that globally or script by script, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5085,7 +4867,6 @@ following example shows: ---- <1> Set the separator scripts to `@@`. <2> Set the separator for `db-schema.sql` to `;`. -==== In this example, the two `test-data` scripts use `@@` as statement separator and only the `db-schema.sql` uses `;`. This configuration specifies that the default separator @@ -5281,7 +5062,6 @@ do not need any special exception treatment (or both). However, Spring lets exce translation be applied transparently through the `@Repository` annotation. The following examples (one for Java configuration and one for XML configuration) show how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5305,7 +5085,6 @@ examples (one for Java configuration and one for XML configuration) show how to ---- -==== The postprocessor automatically looks for all exception translators (implementations of the `PersistenceExceptionTranslator` interface) and advises all beans marked with the @@ -5347,7 +5126,6 @@ definition in the <>. The following excerpt from an XML application context definition shows how to set up a JDBC `DataSource` and a Hibernate `SessionFactory` on top of it: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5376,13 +5154,11 @@ JDBC `DataSource` and a Hibernate `SessionFactory` on top of it: ---- -==== Switching from a local Jakarta Commons DBCP `BasicDataSource` to a JNDI-located `DataSource` (usually managed by an application server) is only a matter of configuration, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5390,7 +5166,6 @@ configuration, as the following example shows: ---- -==== You can also access a JNDI-located `SessionFactory`, using Spring's `JndiObjectFactoryBean` / `` to retrieve and expose it. @@ -5422,7 +5197,6 @@ one current `Session` per transaction. This is roughly equivalent to Spring's synchronization of one Hibernate `Session` per transaction. A corresponding DAO implementation resembles the following example, based on the plain Hibernate API: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5442,7 +5216,6 @@ implementation resembles the following example, based on the plain Hibernate API } } ---- -==== This style is similar to that of the Hibernate reference documentation and examples, except for holding the `SessionFactory` in an instance variable. We strongly recommend @@ -5456,7 +5229,6 @@ You can also set up such a DAO in plain Java (for example, in unit tests). To do instantiate it and call `setSessionFactory(..)` with the desired factory reference. As a Spring bean definition, the DAO would resemble the following: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5468,7 +5240,6 @@ Spring bean definition, the DAO would resemble the following: ---- -==== The main advantage of this DAO style is that it depends on Hibernate API only. No import of any Spring class is required. This is appealing from a non-invasiveness @@ -5511,7 +5282,6 @@ You can annotate the service layer with `@Transactional` annotations and instruc Spring container to find these annotations and provide transactional semantics for these annotated methods. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5536,13 +5306,11 @@ these annotated methods. The following example shows how to do so: } ---- -==== In the container, you need to set up the `PlatformTransactionManager` implementation (as a bean) and a `` entry, opting into `@Transactional` processing at runtime. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5574,7 +5342,6 @@ processing at runtime. The following example shows how to do so: ---- -==== [[orm-hibernate-tx-programmatic]] @@ -5589,7 +5356,6 @@ as a bean reference through a `setTransactionManager(..)` method. Also, the a transaction manager and a business service definition in a Spring application context and an example for a business method implementation: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5633,7 +5399,6 @@ and an example for a business method implementation: } } ---- -==== Spring's `TransactionInterceptor` lets any checked application exception be thrown with the callback code, while `TransactionTemplate` is restricted to unchecked @@ -5738,14 +5503,12 @@ These warnings or exceptions indicate that the connection being accessed is no l valid or JDBC access is no longer valid, possibly because the transaction is no longer active. As an example, here is an actual exception from WebLogic: -==== [literal] [subs="verbatim,quotes"] ---- java.sql.SQLException: The transaction is no longer active - status: 'Committed'. No further JDBC access is allowed within this transaction. ---- -==== You can resolve this warning by making Hibernate aware of the JTA `PlatformTransactionManager` instance, to which it synchronizes (along with Spring). @@ -5830,7 +5593,6 @@ factory bean uses the JPA `PersistenceProvider` auto-detection mechanism (accord JPA's Java SE bootstrapping) and, in most cases, requires you to specify only the persistence unit name. The following XML example configures such a bean: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5840,7 +5602,6 @@ persistence unit name. The following XML example configures such a bean: ---- -==== This form of JPA deployment is the simplest and the most limited. You cannot refer to an existing JDBC `DataSource` bean definition, and no support for global transactions @@ -5859,7 +5620,6 @@ provider than the server's default. Obtaining an `EntityManagerFactory` from JNDI (for example in a Java EE environment), is a matter of changing the XML configuration, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5867,7 +5627,6 @@ is a matter of changing the XML configuration, as the following example shows: ---- -==== This action assumes standard Java EE bootstrapping. The Java EE server auto-detects persistence units (in effect, `META-INF/persistence.xml` files in application jars) and @@ -5909,7 +5668,6 @@ possible to work with custom data sources outside of JNDI and to control the wea process. The following example shows a typical bean definition for a `LocalContainerEntityManagerFactoryBean`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5922,11 +5680,9 @@ process. The following example shows a typical bean definition for a ---- -==== The following example shows a typical `persistence.xml` file: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5937,7 +5693,6 @@ The following example shows a typical `persistence.xml` file: ---- -==== NOTE: The `` shortcut indicates that no scanning for annotated entity classes is supposed to occur. An explicit 'true' value @@ -5997,7 +5752,6 @@ setting up a load-time weaver, delivering auto-detection of the platform (WebLog GlassFish, Tomcat, Resin, JBoss, or VM agent) and automatic propagation of the weaver to all weaver-aware beans: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6006,12 +5760,10 @@ all weaver-aware beans: ... ---- -==== However, you can, if needed, manually specify a dedicated weaver through the `loadTimeWeaver` property, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6021,7 +5773,6 @@ However, you can, if needed, manually specify a dedicated weaver through the ---- -==== No matter how the LTW is configured, by using this technique, JPA applications relying on instrumentation can run in the target platform (for example, Tomcat) without needing an agent. @@ -6040,7 +5791,6 @@ parsed and later retrieved through the persistence unit name. (By default, the c is searched for `META-INF/persistence.xml` files.) The following example configures multiple locations: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -6067,7 +5817,6 @@ multiple locations: ---- -==== The default implementation allows customization of the `PersistenceUnitInfo` instances (before they are fed to the JPA provider) either declaratively (through its properties, which @@ -6082,7 +5831,6 @@ affect all hosted units) or programmatically (through the `LocalContainerEntityManagerFactoryBean` supports background bootstrapping through the `bootstrapExecutor` property, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6092,7 +5840,6 @@ the `bootstrapExecutor` property, as the following example shows: ---- -==== The actual JPA provider bootstrapping is handed off to the specified executor and then, running in parallel, to the application bootstrap thread. The exposed `EntityManagerFactory` @@ -6118,7 +5865,6 @@ using an injected `EntityManagerFactory` or `EntityManager`. Spring can understa if a `PersistenceAnnotationBeanPostProcessor` is enabled. The following example shows a plain JPA DAO implementation that uses the `@PersistenceUnit` annotation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6146,13 +5892,11 @@ that uses the `@PersistenceUnit` annotation: } } ---- -==== The preceding DAO has no dependency on Spring and still fits nicely into a Spring application context. Moreover, the DAO takes advantage of annotations to require the injection of the default `EntityManagerFactory`, as the following example bean definition shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6165,7 +5909,6 @@ injection of the default `EntityManagerFactory`, as the following example bean d ---- -==== As an alternative to explicitly defining a `PersistenceAnnotationBeanPostProcessor`, consider using the Spring `context:annotation-config` XML element in your application @@ -6175,7 +5918,6 @@ post-processors for annotation-based configuration, including Consider the following example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6188,14 +5930,12 @@ Consider the following example: ---- -==== The main problem with such a DAO is that it always creates a new `EntityManager` through the factory. You can avoid this by requesting a transactional `EntityManager` (also called a "`shared EntityManager`" because it is a shared, thread-safe proxy for the actual transactional EntityManager) to be injected instead of the factory. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6211,7 +5951,6 @@ transactional EntityManager) to be injected instead of the factory. The followin } } ---- -==== The `@PersistenceContext` annotation has an optional attribute called `type`, which defaults to `PersistenceContextType.TRANSACTION`. You can use this default to receive a shared @@ -6447,7 +6186,6 @@ the two Spring interfaces used for this purpose. Spring abstracts all marshalling operations behind the `org.springframework.oxm.Marshaller` interface, the main method of which follows: -==== [source,java,indent=0] [subs="verbatim"] ---- @@ -6459,7 +6197,6 @@ Spring abstracts all marshalling operations behind the void marshal(Object graph, Result result) throws XmlMappingException, IOException; } ---- -==== The `Marshaller` interface has one main method, which marshals the given object to a given `javax.xml.transform.Result`. The result is a tagging interface that basically @@ -6493,7 +6230,6 @@ to determine how your O-X technology manages this. Similar to the `Marshaller`, we have the `org.springframework.oxm.Unmarshaller` interface, which the following listing shows: -==== [source,java,indent=0] [subs="verbatim"] ---- @@ -6505,7 +6241,6 @@ interface, which the following listing shows: Object unmarshal(Source source) throws XmlMappingException, IOException; } ---- -==== This interface also has one method, which reads from the given `javax.xml.transform.Source` (an XML input abstraction) and returns the object read. As @@ -6556,7 +6291,6 @@ You can use Spring's OXM for a wide variety of situations. In the following exam use it to marshal the settings of a Spring-managed application as an XML file. In the following example, we use a simple JavaBean to represent the settings: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6573,14 +6307,12 @@ use a simple JavaBean to represent the settings: } } ---- -==== The application class uses this bean to store its settings. Besides a main method, the class has two methods: `saveSettings()` saves the settings bean to a file named `settings.xml`, and `loadSettings()` loads these settings again. The following `main()` method constructs a Spring application context and calls these two methods: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6642,12 +6374,10 @@ constructs a Spring application context and calls these two methods: } } ---- -==== The `Application` requires both a `marshaller` and an `unmarshaller` property to be set. We can do so by using the following `applicationContext.xml`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6659,7 +6389,6 @@ can do so by using the following `applicationContext.xml`: ---- -==== This application context uses Castor, but we could have used any of the other marshaller instances described later in this chapter. Note that, by default, Castor does not require any further @@ -6670,14 +6399,12 @@ application. This sample application produces the following `settings.xml` file: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== @@ -6688,7 +6415,6 @@ You can configure marshallers more concisely by using tags from the OXM namespac make these tags available, you must first reference the appropriate schema in the preamble of the XML configuration file. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6702,7 +6428,7 @@ preamble of the XML configuration file. The following example shows how to do so ---- <1> Reference the `oxm` schema. <2> Specify the `oxm` schema location. -==== + Currently, the schema makes the following elements available: @@ -6713,13 +6439,11 @@ Currently, the schema makes the following elements available: Each tag is explained in its respective marshaller's section. As an example, though, the configuration of a JAXB2 marshaller might resemble the following: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== @@ -6746,7 +6470,6 @@ names that contain schema derived classes. It also offers a `classesToBeBound` p which allows you to set an array of classes to be supported by the marshaller. Schema validation is performed by specifying one or more schema resources to the bean, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6765,7 +6488,6 @@ validation is performed by specifying one or more schema resources to the bean, ---- -==== [[oxm-jaxb2-xsd]] ===== XML Configuration Namespace @@ -6773,18 +6495,15 @@ validation is performed by specifying one or more schema resources to the bean, The `jaxb2-marshaller` element configures a `org.springframework.oxm.jaxb.Jaxb2Marshaller`, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== Alternatively, you can provide the list of classes to bind to the marshaller by using the `class-to-be-bound` child element: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6794,7 +6513,6 @@ Alternatively, you can provide the list of classes to bind to the marshaller by ... ---- -==== The following table describes the available attributes: @@ -6831,7 +6549,6 @@ integration classes reside in the `org.springframework.oxm.castor` package. As with JAXB, the `CastorMarshaller` implements both the `Marshaller` and `Unmarshaller` interface. It can be wired up as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6840,7 +6557,6 @@ interface. It can be wired up as follows: ... ---- -==== [[oxm-castor-mapping]] @@ -6854,7 +6570,6 @@ XML Mapping]. You can set the mapping by using the `mappingLocation` resource property, indicated in the following example with a classpath resource: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6864,7 +6579,6 @@ with a classpath resource: ---- -==== [[oxm-castor-xsd]] ===== XML Configuration Namespace @@ -6872,13 +6586,11 @@ with a classpath resource: The `castor-marshaller` tag configures a `org.springframework.oxm.castor.CastorMarshaller`, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== You can configure the marshaller instance in two ways: by specifying either the location of a mapping file (through the `mapping-location` property) or by identifying Java @@ -6939,7 +6651,6 @@ interface. To operate, it requires the name of the class to marshal in, which yo set using the `targetClass` property. Optionally, you can set the binding name by setting the `bindingName` property. In the following example, we bind the `Flights` class: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6950,7 +6661,6 @@ set using the `targetClass` property. Optionally, you can set the binding name b ... ---- -==== A `JibxMarshaller` is configured for a single class. If you want to marshal multiple classes, you have to configure multiple `JibxMarshaller` instances with different `targetClass` @@ -6962,13 +6672,11 @@ property values. The `jibx-marshaller` tag configures a `org.springframework.oxm.jibx.JibxMarshaller`, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== The following table describes the available attributes: @@ -7008,7 +6716,6 @@ The `XStreamMarshaller` does not require any configuration and can be configured application context directly. To further customize the XML, you can set an alias map, which consists of string aliases mapped to classes, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -7023,7 +6730,6 @@ which consists of string aliases mapped to classes, as the following example sho ... ---- -==== [WARNING] ===== @@ -7035,7 +6741,6 @@ result in security vulnerabilities. If you choose to use the `XStreamMarshaller` to unmarshal XML from an external source, set the `supportedClasses` property on the `XStreamMarshaller`, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -7044,7 +6749,6 @@ set the `supportedClasses` property on the `XStreamMarshaller`, as the following ... ---- -==== Doing so ensures that only the registered classes are eligible for unmarshalling. diff --git a/src/docs/asciidoc/integration-appendix.adoc b/src/docs/asciidoc/integration-appendix.adoc index 12079dc62f..7de948507a 100644 --- a/src/docs/asciidoc/integration-appendix.adoc +++ b/src/docs/asciidoc/integration-appendix.adoc @@ -20,7 +20,6 @@ To use the elements in the `jee` schema, you need to have the following preamble of your Spring XML configuration file. The text in the following snippet references the correct schema so that the elements in the `jee` namespace are available to you: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -34,7 +33,6 @@ correct schema so that the elements in the `jee` namespace are available to you: ---- -==== @@ -43,7 +41,6 @@ correct schema so that the elements in the `jee` namespace are available to you: The following example shows how to use JNDI to look up a data source without the `jee` schema: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -55,12 +52,10 @@ The following example shows how to use JNDI to look up a data source without the ---- -==== The following example shows how to use JNDI to look up a data source with the `jee` schema: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -71,7 +66,6 @@ schema: ---- -==== @@ -81,7 +75,6 @@ schema: The following example shows how to use JNDI to look up an environment variable without `jee`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -94,7 +87,6 @@ The following example shows how to use JNDI to look up an environment variable w ---- -==== The following example shows how to use JNDI to look up an environment variable with `jee`: @@ -113,7 +105,6 @@ The following example shows how to use JNDI to look up an environment variable w The following example shows how to use JNDI to look up multiple environment variables without `jee`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -127,12 +118,10 @@ without `jee`: ---- -==== The following example shows how to use JNDI to look up multiple environment variables with `jee`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -144,7 +133,6 @@ The following example shows how to use JNDI to look up multiple environment vari ---- -==== [[xsd-schemas-jee-jndi-lookup-complex]] @@ -153,7 +141,6 @@ The following example shows how to use JNDI to look up multiple environment vari The following example shows how to use JNDI to look up a data source and a number of different properties without `jee`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -166,12 +153,10 @@ different properties without `jee`: ---- -==== The following example shows how to use JNDI to look up a data source and a number of different properties with `jee`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -183,7 +168,6 @@ different properties with `jee`: expected-type="com.myapp.DefaultThing" proxy-interface="com.myapp.Thing"/> ---- -==== @@ -195,7 +179,6 @@ The `` element configures a reference to a local EJB Stateless The following example shows how to configures a reference to a local EJB Stateless SessionBean without `jee`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -205,19 +188,16 @@ SessionBean without `jee`: ---- -==== The following example shows how to configures a reference to a local EJB Stateless SessionBean with `jee`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== @@ -229,7 +209,6 @@ The `` element configures a reference to a local EJB Stateless The following example shows how to configures a reference to a local EJB Stateless SessionBean and a number of properties without `jee`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -242,12 +221,10 @@ SessionBean and a number of properties without `jee`: ---- -==== The following example shows how to configures a reference to a local EJB Stateless SessionBean and a number of properties with `jee`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -258,7 +235,6 @@ SessionBean and a number of properties with `jee`: lookup-home-on-startup="true" resource-ref="true"> ---- -==== [[xsd-schemas-jee-remote-slsb]] @@ -270,7 +246,6 @@ SessionBean. The following example shows how to configures a reference to a remote EJB Stateless SessionBean without `jee`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -285,12 +260,10 @@ SessionBean without `jee`: ---- -==== The following example shows how to configures a reference to a remote EJB Stateless SessionBean with `jee`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -303,7 +276,6 @@ SessionBean with `jee`: home-interface="com.foo.service.RentalService" refresh-home-on-connect-failure="true"> ---- -==== @@ -321,7 +293,6 @@ the following preamble at the top of your Spring XML configuration file. The tex following snippet references the correct schema so that the elements in the `jms` namespace are available to you: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -335,7 +306,6 @@ are available to you: ---- -==== @@ -359,7 +329,6 @@ To use the elements in the `cache` schema, you need to have the following preamb top of your Spring XML configuration file. The text in the following snippet references the correct schema so that the elements in the `cache` namespace are available to you: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -373,4 +342,3 @@ the correct schema so that the elements in the `cache` namespace are available t ---- -==== diff --git a/src/docs/asciidoc/integration.adoc b/src/docs/asciidoc/integration.adoc index 6ce8b51cc3..e8bd1b5b23 100644 --- a/src/docs/asciidoc/integration.adoc +++ b/src/docs/asciidoc/integration.adoc @@ -42,7 +42,6 @@ usual (Spring) POJOs. Currently, Spring supports the following remoting technolo While discussing the remoting capabilities of Spring, we use the following domain model and corresponding services: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -89,7 +88,6 @@ model and corresponding services: } ---- -==== This section starts by exposing the service to a remote client by using RMI and talk a bit about the drawbacks of using RMI. It then continues with an example that uses Hessian as the @@ -119,7 +117,6 @@ supports the exposing of any non-RMI services via RMI invokers. We first have to set up our service in the Spring container. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -127,12 +124,10 @@ The following example shows how to do so: ---- -==== Next, we have to expose our service by using `RmiServiceExporter`. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -145,7 +140,6 @@ The following example shows how to do so: ---- -==== In the preceding example, we override the port for the RMI registry. Often, your application server also maintains an RMI registry, and it is wise to not interfere with that one. @@ -163,7 +157,6 @@ anonymous port is used to communicate with the service. Our client is a simple object that uses the `AccountService` to manage accounts, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -179,12 +172,10 @@ as the following example shows: } ---- -==== To link in the service on the client, we create a separate Spring container, to contain the following simple object and the service linking configuration bits: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -197,7 +188,6 @@ to contain the following simple object and the service linking configuration bit ---- -==== That is all we need to do to support the remote account service on the client. Spring transparently creates an invoker and remotely enables the account service through the @@ -220,7 +210,6 @@ Hessian communicates through HTTP and does so by using a custom servlet. By usin up such a servlet to expose your services. First, we have to create a new servlet in our application, as shown in the following excerpt from `web.xml`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -235,7 +224,6 @@ our application, as shown in the following excerpt from `web.xml`: /remoting/* ---- -==== If you are familiar with Spring's `DispatcherServlet` principles, you probably know that now you have to create a Spring container configuration resource named @@ -255,7 +243,6 @@ its target exporter. In the newly created application context called `remoting-servlet.xml`, we create a `HessianServiceExporter` to export our services, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -268,7 +255,6 @@ In the newly created application context called `remoting-servlet.xml`, we creat ---- -==== Now we are ready to link in the service at the client. No explicit handler mapping is specified (to map request URLs onto services), so we use `BeanNameUrlHandlerMapping` @@ -279,7 +265,6 @@ within the containing `DispatcherServlet` instance's mapping (as defined earlier Alternatively, you can create a `HessianServiceExporter` in your root application context (for example, in `WEB-INF/applicationContext.xml`), as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -288,14 +273,12 @@ in `WEB-INF/applicationContext.xml`), as the following example shows: ---- -==== In the latter case, you should define a corresponding servlet for this exporter in `web.xml`, with the same end result: The exporter gets mapped to the request path at `/remoting/AccountService`. Note that the servlet name needs to match the bean name of the target exporter. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -309,7 +292,6 @@ the target exporter. The following example shows how to do so: /remoting/AccountService ---- -==== [[remoting-caucho-protocols-hessian-client]] @@ -320,7 +302,6 @@ principles apply as with the RMI example. We create a separate bean factory or application context and mention the following beans where the `SimpleObject` is by using the `AccountService` to manage accounts, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -333,7 +314,6 @@ the `AccountService` to manage accounts, as the following example shows: ---- -==== [[remoting-caucho-protocols-security]] @@ -345,7 +325,6 @@ be applied through using the `web.xml` security features, for example. Usually, you need not use per-user security credentials here. Rather, you can use shared credentials that you define at the `HessianProxyFactoryBean` level (similar to a JDBC `DataSource`), as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -358,7 +337,6 @@ at the `HessianProxyFactoryBean` level (similar to a JDBC `DataSource`), as the ---- -==== In the preceding example, we explicitly mention the `BeanNameUrlHandlerMapping` and set an interceptor, to let only administrators and operators call the beans mentioned in @@ -414,7 +392,6 @@ To expose the `AccountService` (mentioned earlier) within a Spring Web MVC `DispatcherServlet`, the following configuration needs to be in place in the dispatcher's application context, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -423,7 +400,6 @@ dispatcher's application context, as the following example shows: ---- -==== Such an exporter definition is exposed through the `DispatcherServlet` instance's standard mapping facilities, as explained in <>. @@ -431,7 +407,6 @@ mapping facilities, as explained in < ---- -==== In addition, you can define a corresponding servlet for this exporter in `web.xml`, with the servlet name matching the bean name of the target exporter, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -459,7 +432,6 @@ servlet name matching the bean name of the target exporter, as the following exa /remoting/AccountService ---- -==== [[remoting-httpinvoker-client]] @@ -470,7 +442,6 @@ when you use Hessian. By using a proxy, Spring can translate your calls to HTTP POST requests to the URL that points to the exported service. The following example shows how to configure this arrangement: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -479,14 +450,12 @@ shows how to configure this arrangement: ---- -==== As mentioned earlier, you can choose what HTTP client you want to use. By default, the `HttpInvokerProxy` uses the JDK's HTTP functionality, but you can also use the Apache `HttpComponents` client by setting the `httpInvokerRequestExecutor` property. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -494,7 +463,6 @@ The following example shows how to do so: ---- -==== @@ -522,7 +490,6 @@ delegating the call to the business layer. We use Spring's `@Autowired` annotation to express such dependencies on Spring-managed beans. The following example shows our class that extends `SpringBeanAutowiringSupport`: -==== [source,java,indent=0] ---- /** @@ -562,7 +529,6 @@ shows our class that extends `SpringBeanAutowiringSupport`: } ---- -==== Our `AccountServiceEndpoint` needs to run in the same web application as the Spring context to allow for access to Spring's facilities. This is the case by default in Java @@ -586,7 +552,6 @@ dependency injection) to the endpoint instances. Annotation-driven injection through `@Autowired` works as well. The following example shows how to define these beans: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -600,14 +565,12 @@ The following example shows how to define these beans: ... ---- -==== The `AccountServiceEndpoint` can but does not have to derive from Spring's `SpringBeanAutowiringSupport`, since the endpoint in this example is a fully Spring-managed bean. This means that the endpoint implementation can be as follows (without any superclass declared -- and Spring's `@Autowired` configuration annotation is still honored): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -628,7 +591,6 @@ and Spring's `@Autowired` configuration annotation is still honored): } } ---- -==== [[remoting-web-services-jaxws-export-ri]] @@ -663,7 +625,6 @@ return only a JAX-WS service class for us to work with. The latter is the full-f version that can return a proxy that implements our business service interface. In the following example, we use `JaxWsPortProxyFactoryBean` to create a proxy for the `AccountService` endpoint (again): -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -676,7 +637,7 @@ example, we use `JaxWsPortProxyFactoryBean` to create a proxy for the `AccountSe ---- <1> Where `serviceInterface` is our business interface that the clients use. -==== + `wsdlDocumentUrl` is the URL for the WSDL file. Spring needs this at startup time to create the JAX-WS Service. `namespaceUri` corresponds to the `targetNamespace` in the @@ -686,7 +647,6 @@ corresponds to the port name in the .wsdl file. Accessing the web service is easy, as we have a bean factory for it that exposes it as an interface called `AccountService`. The following example shows how we can wire this up in Spring: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -695,12 +655,10 @@ exposes it as an interface called `AccountService`. The following example shows ---- -==== From the client code, we can access the web service as if it were a normal class, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -717,7 +675,6 @@ as the following example shows: } } ---- -==== NOTE: The above is slightly simplified in that JAX-WS requires endpoint interfaces and implementation classes to be annotated with `@WebService`, `@SOAPBinding` etc @@ -740,7 +697,6 @@ messaging. The following interface is used on both the server and the client sides: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -751,11 +707,9 @@ The following interface is used on both the server and the client sides: public void cancelAccount(Long accountId); } ---- -==== The following simple implementation of the preceding interface is used on the server-side: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -768,12 +722,10 @@ The following simple implementation of the preceding interface is used on the se } } ---- -==== The following configuration file contains the JMS-infrastructure beans that are shared on both the client and the server: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -793,7 +745,6 @@ on both the client and the server: ---- -==== [[remoting-jms-server]] @@ -802,7 +753,6 @@ on both the client and the server: On the server, you need to expose the service object that uses the `JmsInvokerServiceExporter`, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -844,7 +794,6 @@ On the server, you need to expose the service object that uses the } } ---- -==== [[remoting-jms-client]] @@ -856,7 +805,6 @@ interface ( `CheckingAccountService`). The following example defines beans that you can inject into other client-side objects (and the proxy takes care of forwarding the call to the server-side object via JMS): -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -894,7 +842,6 @@ proxy takes care of forwarding the call to the server-side object via JMS): } } ---- -==== @@ -1054,13 +1001,11 @@ There is built-in support for the following: For example, to switch to Apache HttpComponents, you can use the following: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory()); ---- -==== Each `ClientHttpRequestFactory` exposes configuration options specific to the underlying HTTP client library -- for example, for credentials, connection pooling, and other details. @@ -1077,18 +1022,15 @@ either as a `String` variable argument, or as `Map`. The following example uses a `String` variable argument: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- String result = restTemplate.getForObject( "http://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42", "21"); ---- -==== The following example uses a `Map`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1097,11 +1039,9 @@ The following example uses a `Map`: String result = restTemplate.getForObject( "http://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars); ---- -==== Keep in mind URI templates are automatically encoded, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1109,7 +1049,6 @@ Keep in mind URI templates are automatically encoded, as the following example s // Results in request to "http://example.com/hotel%20list" ---- -==== You can use the `uriTemplateHandler` property of `RestTemplate` to customize how URIs are encoded. Alternatively, you can prepare a `java.net.URI` and pass it into one of the `RestTemplate` @@ -1123,7 +1062,6 @@ For more details on working with and encoding URIs, see You can use the `exchange()` methods to specify request headers, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1139,7 +1077,6 @@ You can use the `exchange()` methods to specify request headers, as the followin String responseHeader = response.getHeaders().getFirst("MyResponseHeader"); String body = response.getBody(); ---- -==== You can obtain response headers through many `RestTemplate` method variants that return `ResponseEntity`. @@ -1152,11 +1089,9 @@ content with the help of an `HttpMessageConverter`. On a POST, an input object is serialized to the request body, as the following example shows: -==== ---- URI location = template.postForLocation("http://example.com/people", person); ---- -==== You need not explicitly set the Content-Type header of the request. In most cases, you can find a compatible message converter based on the source `Object` type, and the chosen @@ -1166,11 +1101,9 @@ turn, influences what message converter is selected. On a GET, the body of the response is deserialized to an output `Object`, as the following example shows: -==== ---- Person person = restTemplate.getForObject("http://example.com/people/{id}", Person.class, 42); ---- -==== The `Accept` header of the request does not need to be explicitly set. In most cases, a compatible message converter can be found based on the expected response type, which @@ -1266,7 +1199,6 @@ and writes the media type supported by the Java I/O API. You can specify a http://wiki.fasterxml.com/JacksonJsonViews[Jackson JSON View] to serialize only a subset of the object properties, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1278,7 +1210,6 @@ to serialize only a subset of the object properties, as the following example sh ResponseEntity response = template.exchange(requestEntity, String.class); ---- -==== [[rest-template-multipart]] ===== Multipart @@ -1288,7 +1219,6 @@ either `Object` instances that represent part content or `HttpEntity` instances headers for a part. `MultipartBodyBuilder` provides a convenient API to prepare a multipart request, as the following example shows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -1299,7 +1229,6 @@ multipart request, as the following example shows: MultiValueMap> parts = builder.build(); ---- -==== In most cases, you do not have to specify the `Content-Type` for each part. The content type is determined automatically based on the `HttpMessageConverter` chosen to serialize it @@ -1309,14 +1238,12 @@ builder `part` methods. Once the `MultiValueMap` is ready, you can pass it to the `RestTemplate`, as the following example shows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- MultipartBodyBuilder builder = ...; template.postForObject("http://example.com/upload", builder.build(), Void.class); ---- -==== If the `MultiValueMap` contains at least one non-`String` value, which could also be represent regular form data (that is, `application/x-www-form-urlencoded`), you need not @@ -1397,7 +1324,6 @@ practice and use the EJB Business Methods Interface pattern, so that the EJB's l interface extends a non-EJB-specific business methods interface. We call this business methods interface `MyComponent`. The following example shows such an interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1405,7 +1331,6 @@ business methods interface `MyComponent`. The following example shows such an in ... } ---- -==== One of the main reasons to use the Business Methods Interface pattern is to ensure that synchronization between method signatures in local interface and bean implementation @@ -1418,7 +1343,6 @@ controller to the EJB implementation is to expose a setter method of type `MyCom on the controller. This saves the reference as an instance variable in the controller. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1428,7 +1352,6 @@ controller. The following example shows how to do so: this.myComponent = myComponent; } ---- -==== We can subsequently use this instance variable in any business method in the controller. Now, assuming we obtain our controller object out of a Spring container, we can @@ -1436,7 +1359,6 @@ Now, assuming we obtain our controller object out of a Spring container, we can which is the EJB proxy object. We configure the proxy and set the `myComponent` property of the controller with the following configuration entry: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1450,7 +1372,6 @@ which is the EJB proxy object. We configure the proxy and set the ---- -==== A lot of work happens behind the scenes, courtesy of the Spring AOP framework, although you are not forced to work with AOP concepts to enjoy the results. The @@ -1466,7 +1387,6 @@ Alternatively (and preferably in case of many such proxy definitions), consider the `` configuration element in Spring's "`jee`" namespace. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1477,7 +1397,6 @@ The following example shows how to do so: ---- -==== This EJB access mechanism delivers huge simplification of application code. The web tier code (or other EJB client code) has no dependence on the use of EJB. To @@ -1691,13 +1610,11 @@ managed implementation of the `ConnectionFactory`. The standard API involves creating many intermediate objects. To send a message, the following 'API' walk is performed: -==== [literal] [subs="verbatim,quotes"] ---- ConnectionFactory->Connection->Session->MessageProducer->send ---- -==== Between the `ConnectionFactory` and the `Send` operation, three intermediate objects are created and destroyed. To optimize the resource usage and increase @@ -1917,7 +1834,6 @@ that takes no destination argument uses the default destination. The following example uses the `MessageCreator` callback to create a text message from the supplied `Session` object: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1952,7 +1868,6 @@ supplied `Session` object: } } ---- -==== In the preceding example, the `JmsTemplate` is constructed by passing a reference to a `ConnectionFactory`. As an alternative, a zero-argument constructor and @@ -1995,7 +1910,6 @@ gives you access to the message after it has been converted but before it is sen following example shows how to modify a message header and a property after a `java.util.Map` is converted to a message: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2012,11 +1926,9 @@ following example shows how to modify a message header and a property after a }); } ---- -==== This results in a message of the following form: -==== [literal] [subs="verbatim,quotes"] ---- @@ -2034,7 +1946,6 @@ MapMessage={ } } ---- -==== [[jms-callbacks]] @@ -2082,7 +1993,6 @@ ensure that your implementation is thread-safe. The following example shows a simple implementation of an MDP: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2108,7 +2018,6 @@ The following example shows a simple implementation of an MDP: } } ---- -==== Once you have implemented your `MessageListener`, it is time to create a message listener container. @@ -2116,7 +2025,6 @@ container. The following example shows how to define and configure one of the message listener containers that ships with Spring (in this case, `DefaultMessageListenerContainer`): -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2130,7 +2038,6 @@ containers that ships with Spring (in this case, `DefaultMessageListenerContaine **** ---- -==== See the Spring javadoc of the various message listener containers (all of which implement {api-spring-framework}/jms/listener/MessageListenerContainer.html[MessageListenerContainer]) @@ -2145,7 +2052,6 @@ a similar contract to the JMS `MessageListener` interface but also gives the mes method access to the JMS `Session` from which the `Message` was received. The following listing shows the definition of the `SessionAwareMessageListener` interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2156,7 +2062,6 @@ The following listing shows the definition of the `SessionAwareMessageListener` void onMessage(Message message, Session session) throws JMSException; } ---- -==== You can choose to have your MDPs implement this interface (in preference to the standard JMS `MessageListener` interface) if you want your MDPs to be able to respond to any @@ -2183,7 +2088,6 @@ messaging support. In a nutshell, it lets you expose almost any class as an MDP Consider the following interface definition: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2198,7 +2102,6 @@ Consider the following interface definition: void handleMessage(Serializable message); } ---- -==== Notice that, although the interface extends neither the `MessageListener` nor the `SessionAwareMessageListener` interface, you can still use it @@ -2208,7 +2111,6 @@ various `Message` types that they can receive and handle. Now consider the following implementation of the `MessageDelegate` interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2216,13 +2118,11 @@ Now consider the following implementation of the `MessageDelegate` interface: // implementation elided for clarity... } ---- -==== In particular, note how the preceding implementation of the `MessageDelegate` interface (the `DefaultMessageDelegate` class) has no JMS dependencies at all. It truly is a POJO that we can make into an MDP through the following configuration: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2240,7 +2140,6 @@ POJO that we can make into an MDP through the following configuration: **** ---- -==== The next example shows another MDP that can handle only receiving JMS `TextMessage` messages. Notice how the message handling method is actually called @@ -2250,7 +2149,6 @@ also how the `receive(..)` method is strongly typed to receive and respond only `TextMessage` messages. The following listing shows the definition of the `TextMessageDelegate` interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2259,11 +2157,9 @@ The following listing shows the definition of the `TextMessageDelegate` interfac void receive(TextMessage message); } ---- -==== The following listing shows a class that implements the `TextMessageDelegate` interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2271,11 +2167,9 @@ The following listing shows a class that implements the `TextMessageDelegate` in // implementation elided for clarity... } ---- -==== The configuration of the attendant `MessageListenerAdapter` would then be as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2290,7 +2184,6 @@ The configuration of the attendant `MessageListenerAdapter` would then be as fol ---- -==== Note that, if the `messageListener` receives a JMS `Message` of a type other than `TextMessage`, an `IllegalStateException` is thrown (and subsequently @@ -2298,7 +2191,6 @@ swallowed). Another of the capabilities of the `MessageListenerAdapter` class is ability to automatically send back a response `Message` if a handler method returns a non-void value. Consider the following interface and class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2316,7 +2208,6 @@ non-void value. Consider the following interface and class: // implementation elided for clarity... } ---- -==== If you use the `DefaultResponsiveTextMessageDelegate` in conjunction with a `MessageListenerAdapter`, any non-null value that is returned from the execution of @@ -2346,7 +2237,6 @@ has committed but message processing failed to commit. Consider the following bean definition: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2357,7 +2247,6 @@ Consider the following bean definition: **** ---- -==== To participate in an externally managed transaction, you need to configure a transaction manager and use a listener container that supports externally managed @@ -2373,18 +2262,15 @@ semantics, at the expense of XA transaction log overhead). The following bean definition creates a transaction manager: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== Then we need to add it to our earlier container configuration. The container takes care of the rest. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2396,7 +2282,6 @@ takes care of the rest. The following example shows how to do so: ---- <1> Our transaction manager. -==== @@ -2409,7 +2294,6 @@ automatically determine the `ActivationSpec` class name from the provider's `ResourceAdapter` class name. Therefore, it is typically possible to provide Spring's generic `JmsActivationSpecConfig`, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2423,13 +2307,11 @@ Spring's generic `JmsActivationSpecConfig`, as the following example shows: ---- -==== Alternatively, you can set up a `JmsMessageEndpointManager` with a given `ActivationSpec` object. The `ActivationSpec` object may also come from a JNDI lookup (using ``). The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2444,12 +2326,10 @@ Alternatively, you can set up a `JmsMessageEndpointManager` with a given ---- -==== Using Spring's `ResourceAdapterFactoryBean`, you can configure the target `ResourceAdapter` locally, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2464,7 +2344,6 @@ locally, as the following example shows: ---- -==== The specified `WorkManager` can also point to an environment-specific thread pool -- typically through a `SimpleTaskWorkManager` instance's `asyncTaskExecutor` property. Consider @@ -2504,7 +2383,6 @@ The easiest way to receive a message asynchronously is to use the annotated list endpoint infrastructure. In a nutshell, it lets you expose a method of a managed bean as a JMS listener endpoint. The following example shows how to use it: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2515,7 +2393,6 @@ bean as a JMS listener endpoint. The following example shows how to use it: public void processOrder(String data) { ... } } ---- -==== The idea of the preceding example is that, whenever a message is available on the `javax.jms.Destination` `myDestination`, the `processOrder` method is invoked @@ -2539,7 +2416,6 @@ declarations to it. To enable support for `@JmsListener` annotations, you can add `@EnableJms` to one of your `@Configuration` classes, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2558,7 +2434,6 @@ your `@Configuration` classes, as the following example shows: } } ---- -==== By default, the infrastructure looks for a bean named `jmsListenerContainerFactory` as the source for the factory to use to create message listener containers. In this @@ -2575,7 +2450,6 @@ for details and examples. If you prefer <>, you can use the `` element, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2589,7 +2463,6 @@ element, as the following example shows: ---- -==== [[jms-annotated-programmatic-registration]] @@ -2600,7 +2473,6 @@ the container for that model. The infrastructure lets you programmatically confi in addition to the ones that are detected by the `JmsListener` annotation. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2620,7 +2492,6 @@ The following example shows how to do so: } } ---- -==== In the preceding example, we used `SimpleJmsListenerEndpoint`, which provides the actual `MessageListener` to invoke. However, you could also build your own endpoint variant @@ -2637,7 +2508,6 @@ So far, we have been injecting a simple `String` in our endpoint, but it can act have a very flexible method signature. In the following example, we rewrite it to inject the `Order` with a custom header: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2650,7 +2520,6 @@ a custom header: } } ---- -==== The main elements you can inject in JMS listener endpoints are as follows: @@ -2674,14 +2543,12 @@ The ability to inject Spring's `Message` abstraction is particularly useful to b from all the information stored in the transport-specific message without relying on transport-specific API. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @JmsListener(destination = "myDestination") public void processOrder(Message order) { ... } ---- -==== Handling of method arguments is provided by `DefaultMessageHandlerMethodFactory`, which you can further customize to support additional method arguments. You can customize the conversion and validation @@ -2690,7 +2557,6 @@ support there as well. For instance, if we want to make sure our `Order` is valid before processing it, we can annotate the payload with `@Valid` and configure the necessary validator, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2711,7 +2577,6 @@ annotate the payload with `@Valid` and configure the necessary validator, as the } } ---- -==== [[jms-annotated-response]] @@ -2727,7 +2592,6 @@ messaging abstraction. Assuming that our `processOrder` method should now return an `OrderStatus`, we can write it to automatically send a response, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2738,7 +2602,6 @@ to automatically send a response, as the following example shows: return status; } ---- -==== TIP: If you have several `@JmsListener`-annotated methods, you can also place the `@SendTo` annotation at the class level to share a default reply destination. @@ -2746,7 +2609,6 @@ annotation at the class level to share a default reply destination. If you need to set additional headers in a transport-independent manner, you can return a `Message` instead, with a method similar to the following: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2760,13 +2622,11 @@ If you need to set additional headers in a transport-independent manner, you can .build(); } ---- -==== If you need to compute the response destination at runtime, you can encapsulate your response in a `JmsResponse` instance that also provides the destination to use at runtime. We can rewrite the previous example as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2780,13 +2640,11 @@ example as follows: return JmsResponse.forQueue(response, "status"); } ---- -==== Finally, if you need to specify some QoS values for the response such as the priority or the time to live, you can configure the `JmsListenerContainerFactory` accordingly, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2806,7 +2664,6 @@ as the following example shows: } } ---- -==== @@ -2816,7 +2673,6 @@ as the following example shows: Spring provides an XML namespace for simplifying JMS configuration. To use the JMS namespace elements, you need to reference the JMS schema, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2833,7 +2689,7 @@ namespace elements, you need to reference the JMS schema, as the following examp ---- <1> Referencing the JMS schema. -==== + The namespace consists of three top-level elements: ``, `` and ``. `` enables the use of <>. `` and `` child elements. The following example shows a basic configuration for two listeners: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2853,7 +2708,6 @@ following example shows a basic configuration for two listeners: ---- -==== The preceding example is equivalent to creating two distinct listener container bean definitions and two distinct `MessageListenerAdapter` bean definitions, as shown @@ -2912,7 +2766,6 @@ You can automatically expose such settings as a `JmsListenerContainerFactory` by specifying the `id` of the bean to expose through the `factory-id` attribute, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2928,7 +2781,6 @@ as the following example shows: ---- -==== The following table describes all available attributes. See the class-level javadoc of the {api-spring-framework}/jms/listener/AbstractMessageListenerContainer.html[`AbstractMessageListenerContainer`] @@ -3042,7 +2894,6 @@ also provides a discussion of transaction choices and message redelivery scenari Configuring a JCA-based listener container with the `jms` schema support is very similar, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3055,7 +2906,6 @@ as the following example shows: ---- -==== The following table describes the available configuration options for the JCA variant: @@ -3158,7 +3008,6 @@ The core class in Spring's JMX framework is the `MBeanExporter`. This class is responsible for taking your Spring beans and registering them with a JMX `MBeanServer`. For example, consider the following class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3195,13 +3044,11 @@ For example, consider the following class: } } ---- -==== To expose the properties and methods of this bean as attributes and operations of an MBean, you can configure an instance of the `MBeanExporter` class in your configuration file and pass in the bean, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3220,7 +3067,6 @@ configuration file and pass in the bean, as the following example shows: ---- -==== The pertinent bean definition from the preceding configuration snippet is the `exporter` bean. The `beans` property tells the `MBeanExporter` exactly which of your beans must be @@ -3256,7 +3102,6 @@ You can also ensure that a specific `MBeanServer` is used by setting the value o `MBeanExporter` instance's `server` property to the `MBeanServer` value returned by an `MBeanServerFactoryBean`, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3284,7 +3129,6 @@ You can also ensure that a specific `MBeanServer` is used by setting the value o ---- -==== In the preceding example, an instance of `MBeanServer` is created by the `MBeanServerFactoryBean` and is supplied to the `MBeanExporter` through the `server` property. When you supply your own @@ -3302,7 +3146,6 @@ used. However, when multiple instances exist, the exporter might pick the wrong In such cases, you should use the `MBeanServer` `agentId` to indicate which instance to be used, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3319,14 +3162,12 @@ be used, as the following example shows: ---- -==== For platforms or cases where the existing `MBeanServer` has a dynamic (or unknown) `agentId` that is retrieved through lookup methods, you should use <>, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3342,7 +3183,6 @@ as the following example shows: ---- -==== [[jmx-exporting-lazy]] @@ -3363,7 +3203,6 @@ registered as-is with the `MBeanServer` without further intervention from Spring to be automatically detected by the `MBeanExporter` by setting the `autodetect` property to `true`, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3373,7 +3212,6 @@ property to `true`, as the following example shows: ---- -==== In the preceding example, the bean called `spring:mbean=true` is already a valid JMX MBean and is automatically registered by Spring. By default, a bean that is autodetected for JMX @@ -3428,7 +3266,6 @@ values. The following example shows how to change from the default registration behavior to the `REPLACE_EXISTING` behavior: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3450,7 +3287,6 @@ behavior to the `REPLACE_EXISTING` behavior: ---- -==== @@ -3504,7 +3340,6 @@ an operation or an attribute. The following example shows the annotated version of the `JmxTestBean` class that we used in <>: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3565,7 +3400,6 @@ used in <>: } ---- -==== In the preceding example, you can see that the `JmxTestBean` class is marked with the `ManagedResource` annotation and that this `ManagedResource` annotation is configured with a set of @@ -3586,7 +3420,6 @@ the management interface to contain only one operation (`add(int, int)`) when yo The following configuration shows how you can configure the `MBeanExporter` to use the `MetadataMBeanInfoAssembler`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3618,7 +3451,6 @@ The following configuration shows how you can configure the `MBeanExporter` to u ---- -==== In the preceding example, an `MetadataMBeanInfoAssembler` bean has been configured with an instance of the `AnnotationJmxAttributeSource` class and passed to the `MBeanExporter` @@ -3726,7 +3558,6 @@ the `MetadataMBeanInfoAssembler`, which votes to include any bean that is marked with the `ManagedResource` attribute. The default approach in this case is to use the bean name as the `ObjectName`, which results in a configuration similar to the following: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3751,7 +3582,6 @@ bean name as the `ObjectName`, which results in a configuration similar to the f ---- -==== Notice that, in the preceding configuration, no beans are passed to the `MBeanExporter`. However, the `JmxTestBean` is still registered, since it is marked with the `ManagedResource` @@ -3777,7 +3607,6 @@ and removing the need for your beans to implement the MBean interfaces. Consider the following interface, which is used to define a management interface for the `JmxTestBean` class that we showed earlier: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3797,13 +3626,11 @@ Consider the following interface, which is used to define a management interface } ---- -==== This interface defines the methods and properties that are exposed as operations and attributes on the JMX MBean. The following code shows how to configure Spring JMX to use this interface as the definition for the management interface: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3831,7 +3658,6 @@ this interface as the definition for the management interface: ---- -==== In the preceding example, the `InterfaceBasedMBeanInfoAssembler` is configured to use the `IJmxTestBean` interface when constructing the management interface for any bean. It is @@ -3859,7 +3685,6 @@ management interface. that are exposed to JMX as attributes and operations. The following code shows a sample configuration: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3878,7 +3703,6 @@ configuration: ---- -==== In the preceding example, you can see that the `add` and `myOperation` methods are exposed as JMX operations, and `getName()`, `setName(String)`, and `getAge()` are exposed as the @@ -3914,7 +3738,6 @@ that corresponds to the bean key. If no entry is found or if the `Properties` in The following code shows a sample configuration for the `KeyNamingStrategy`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3947,7 +3770,6 @@ The following code shows a sample configuration for the `KeyNamingStrategy`: ---- -==== The preceding example configures an instance of `KeyNamingStrategy` with a `Properties` instance that is merged from the `Properties` instance defined by the mapping property and the @@ -3967,7 +3789,6 @@ the `ObjectName`. attribute on each bean to create the `ObjectName`. The following code shows the configuration for the `MetadataNamingStrategy`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3996,7 +3817,6 @@ configuration for the `MetadataNamingStrategy`: ---- -==== If no `objectName` has been provided for the `ManagedResource` attribute, an `ObjectName` is created with the following @@ -4004,13 +3824,11 @@ format: _[fully-qualified-package-name]:type=[short-classname],name=[bean-name]_ example, the generated `ObjectName` for the following bean would be `com.example:type=MyClass,name=myBean`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== [[jmx-context-mbeanexport]] @@ -4025,7 +3843,6 @@ always enabled as well). In fact, rather than defining an `MBeanExporter` bean, simpler syntax is supported by the `@EnableMBeanExport` `@Configuration` annotation, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4035,18 +3852,15 @@ as the following example shows: } ---- -==== If you prefer XML-based configuration, the `` element serves the same purpose and is shown in the following listing: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== If necessary, you can provide a reference to a particular MBean `server`, and the `defaultDomain` attribute (a property of `AnnotationMBeanExporter`) accepts an alternate @@ -4054,7 +3868,6 @@ value for the generated MBean `ObjectName` domains. This is used in place of the fully qualified package name as described in the previous section on <>, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4064,17 +3877,14 @@ fully qualified package name as described in the previous section on } ---- -==== The following example shows the XML equivalent of the preceding annotation-based example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== CAUTION: Do not use interface-based AOP proxies in combination with autodetection of JMX annotations in your bean classes. Interface-based proxies "`hide`" the target class, which @@ -4099,13 +3909,11 @@ connectors. To have Spring JMX create, start, and expose a JSR-160 `JMXConnectorServer`, you can use the following configuration: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== By default, `ConnectorServerFactoryBean` creates a `JMXConnectorServer` bound to `service:jmx:jmxmp://localhost:9875`. The `serverConnector` bean thus exposes the @@ -4118,7 +3926,6 @@ To specify another URL and register the `JMXConnectorServer` itself with the `MBeanServer`, you can use the `serviceUrl` and `ObjectName` properties, respectively, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4129,14 +3936,12 @@ as the following example shows: value="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/myconnector"/> ---- -==== If the `ObjectName` property is set, Spring automatically registers your connector with the `MBeanServer` under that `ObjectName`. The following example shows the full set of parameters that you can pass to the `ConnectorServerFactoryBean` when creating a `JMXConnector`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4154,7 +3959,6 @@ parameters that you can pass to the `ConnectorServerFactoryBean` when creating a ---- -==== Note that, when you use a RMI-based connector, you need the lookup service (`tnameserv` or `rmiregistry`) to be started in order for the name registration to complete. If you @@ -4162,7 +3966,6 @@ use Spring to export remote services for you through RMI, Spring has already constructed an RMI registry. If not, you can easily start a registry by using the following snippet of configuration: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4170,7 +3973,6 @@ snippet of configuration: ---- -==== [[jmx-jsr160-client]] @@ -4179,7 +3981,6 @@ snippet of configuration: To create an `MBeanServerConnection` to a remote JSR-160-enabled `MBeanServer`, you can use the `MBeanServerConnectionFactoryBean`, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4187,7 +3988,6 @@ To create an `MBeanServerConnection` to a remote JSR-160-enabled `MBeanServer`, ---- -==== [[jmx-jsr160-protocols]] @@ -4200,7 +4000,6 @@ other providers or JMX implementations (such as http://mx4j.sourceforge.net[MX4J can take advantage of protocols such as SOAP or Hessian over simple HTTP or SSL and others, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4209,7 +4008,6 @@ as the following example shows: ---- -==== In the preceding example, we used MX4J 3.0.0. See the official MX4J documentation for more information. @@ -4224,7 +4022,6 @@ local or remote `MBeanServer`. These proxies provide you with a standard Java in through which you can interact with your MBeans. The following code shows how to configure a proxy for an MBean running in a local `MBeanServer`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4233,7 +4030,6 @@ proxy for an MBean running in a local `MBeanServer`: ---- -==== In the preceding example, you can see that a proxy is created for the MBean registered under the `ObjectName` of `bean:name=testBean`. The set of interfaces that the proxy implements @@ -4246,7 +4042,6 @@ The `MBeanProxyFactoryBean` can create a proxy to any MBean that is accessible t you can override this and provide an `MBeanServerConnection` that points to a remote `MBeanServer` to cater for proxies that point to remote MBeans: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4261,7 +4056,6 @@ you can override this and provide an `MBeanServerConnection` that points to a re ---- -==== In the preceding example, we create an `MBeanServerConnection` that points to a remote machine that uses the `MBeanServerConnectionFactoryBean`. This `MBeanServerConnection` is then @@ -4287,7 +4081,6 @@ example, consider the scenario where one would like to be informed (through a `Notification`) each and every time an attribute of a target MBean changes. The following example writes notifications to the console: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4312,12 +4105,10 @@ example writes notifications to the console: } ---- -==== The following example adds `ConsoleLoggingNotificationListener` (defined in the preceding example) to `notificationListenerMappings`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4345,7 +4136,6 @@ example) to `notificationListenerMappings`: ---- -==== With the preceding configuration in place, every time a JMX `Notification` is broadcast from the target MBean (`bean:name=testBean1`), the `ConsoleLoggingNotificationListener` bean @@ -4356,7 +4146,6 @@ it deems appropriate in response to the `Notification`. You can also use straight bean names as the link between exported beans and listeners, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4384,14 +4173,12 @@ as the following example shows: ---- -==== If you want to register a single `NotificationListener` instance for all of the beans that the enclosing `MBeanExporter` exports, you can use the special wildcard (`{asterisk}`) as the key for an entry in the `notificationListenerMappings` property map, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4403,7 +4190,6 @@ map, as the following example shows: ---- -==== If you need to do the inverse (that is, register a number of distinct listeners against an MBean), you must instead use the `notificationListeners` list property (in @@ -4418,7 +4204,6 @@ object that can be used in advanced JMX notification scenarios. The configuration when using `NotificationListenerBean` instances is not wildly different to what was presented previously, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4453,14 +4238,12 @@ different to what was presented previously, as the following example shows: ---- -==== The preceding example is equivalent to the first notification example. Assume, then, that we want to be given a handback object every time a `Notification` is raised and that we also want to filter out extraneous `Notifications` by supplying a `NotificationFilter`. The following example accomplishes these goals: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4510,7 +4293,6 @@ we also want to filter out extraneous `Notifications` by supplying a ---- -==== (For a full discussion of what a handback object is and, indeed, what a `NotificationFilter` is, see the section of the JMX @@ -4555,7 +4337,6 @@ published, and invoke the `sendNotification(Notification)` on the In the following example, exported instances of the `JmxTestBean` publish a `NotificationEvent` every time the `add(int, int)` operation is invoked: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4590,7 +4371,6 @@ In the following example, exported instances of the `JmxTestBean` publish a } ---- -==== The `NotificationPublisher` interface and the machinery to get it all working is one of the nicer features of Spring's JMX support. It does, however, come with the price tag of @@ -4698,13 +4478,11 @@ in a non-managed mode). In managed mode, you can access a `ConnectionFactory` from JNDI. Its properties are configured in the application server. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== In non-managed mode, you must configure the `ConnectionFactory` you want to use in the configuration of Spring as a JavaBean. The `LocalConnectionFactoryBean` class offers @@ -4712,7 +4490,6 @@ this setup style, passing in the `ManagedConnectionFactory` implementation of yo connector, exposing the application-level CCI `ConnectionFactory`. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4726,7 +4503,6 @@ shows how to do so: ---- -==== NOTE: You cannot directly instantiate a specific `ConnectionFactory`. You need to go through the corresponding implementation of the `ManagedConnectionFactory` interface for your @@ -4748,7 +4524,6 @@ in the application server (in managed mode) or on the corresponding local `ManagedConnectionFactory` implementation. The following listing shows the relevant parts of the `ConnectionFactory` interface definition: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4759,7 +4534,6 @@ shows the relevant parts of the `ConnectionFactory` interface definition: ... } ---- -==== Spring provides a `ConnectionSpecConnectionFactoryAdapter` that lets you specify a `ConnectionSpec` instance to use for all operations on a given factory. If the adapter's @@ -4767,7 +4541,6 @@ Spring provides a `ConnectionSpecConnectionFactoryAdapter` that lets you specify with the `ConnectionSpec` argument. Otherwise, the adapter uses the variant without that argument. The following example shows how to configure a `ConnectionSpecConnectionFactoryAdapter`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4793,7 +4566,6 @@ The following example shows how to configure a `ConnectionSpecConnectionFactoryA ---- -==== [[cci-config-single-connection]] @@ -4806,7 +4578,6 @@ application shutdown. This class exposes special `Connection` proxies that behav accordingly, all sharing the same underlying physical connection. The following example shows how to use the `SingleConnectionFactory` adapter class: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4827,7 +4598,6 @@ shows how to use the `SingleConnectionFactory` adapter class: ---- -==== NOTE: This `ConnectionFactory` adapter cannot directly be configured with a `ConnectionSpec`. You can use an intermediary `ConnectionSpecConnectionFactoryAdapter` that the @@ -4864,7 +4634,6 @@ To create an input `Record`, you can use a dedicated implementation of the `RecordCreator` interface. The following listing shows the `RecordCreator` interface definition: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4874,7 +4643,6 @@ interface definition: } ---- -==== The `createRecord(..)` method receives a `RecordFactory` instance as a parameter, which corresponds to the `RecordFactory` of the `ConnectionFactory` used. @@ -4882,7 +4650,6 @@ You can use this reference to create `IndexedRecord` or `MappedRecord` instances following sample shows how to use the `RecordCreator` interface and indexed or mapped records: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4896,14 +4663,12 @@ records: } ---- -==== You can use an output `Record` to receive data back from the EIS. Hence, you can pass a specific implementation of the `RecordExtractor` interface to Spring's `CciTemplate` to extract data from the output `Record`. The following listing shows the `RecordExtractor` interface definition: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4913,11 +4678,9 @@ implementation of the `RecordExtractor` interface to Spring's } ---- -==== The following example shows how to use the `RecordExtractor` interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4933,7 +4696,6 @@ The following example shows how to use the `RecordExtractor` interface: } ---- -==== [[cci-using-template]] @@ -4950,7 +4712,6 @@ The JCA CCI specification defines two distinct methods to call operations on an CCI `Interaction` interface provides two execute method signatures, as the following listing shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4966,7 +4727,6 @@ listing shows: } ---- -==== Depending on the template method called, `CciTemplate` knows which `execute` method to call on the interaction. In any case, a correctly initialized `InteractionSpec` @@ -4982,7 +4742,6 @@ You can use `CciTemplate.execute(..)` in two ways: With the first approach, the following methods (which directly correspond to those on the `Interaction` interface) of the template are used: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4996,13 +4755,11 @@ With the first approach, the following methods (which directly correspond to tho } ---- -==== With the second approach, we need to specify the record creation and record extraction strategies as arguments. The interfaces used are those describe in the <>. The following listing shows the corresponding `CciTemplate` methods: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5025,7 +4782,6 @@ on record conversion>>. The following listing shows the corresponding `CciTempla } ---- -==== Unless the `outputRecordCreator` property is set on the template (see the following section), every method calls the corresponding `execute` method of the CCI @@ -5038,7 +4794,6 @@ output `Record` as its return value. `Record` instances to pass into corresponding `CciTemplate.execute(..)` methods. The following listing shows the `CciTemplate` interface definition: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5050,7 +4805,6 @@ The following listing shows the `CciTemplate` interface definition: } ---- -==== [[cci-using-dao]] @@ -5063,7 +4817,6 @@ Internally, this class creates a `CciTemplate` instance for a passed-in `ConnectionFactory`, exposing it to concrete data access implementations in subclasses. The following example shows how to use `CciDaoSupport`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5087,7 +4840,6 @@ The following example shows how to use `CciDaoSupport`: } ---- -==== [[automatic-output-generation]] @@ -5104,18 +4856,15 @@ This property holds an implementation of the < ---- -==== NOTE: As the `CciTemplate` class is thread-safe, it is usually configured as a shared instance. @@ -5200,7 +4948,6 @@ was created. The latter can be useful (for example, to get an associated `RecordFactory` instance and create indexed/mapped records). The following listing shows the `ConnectionCallback` interface definition: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5211,13 +4958,11 @@ The following listing shows the `ConnectionCallback` interface definition: } ---- -==== The `InteractionCallback` interface provides the CCI `Interaction` (to perform custom operations on it) plus the corresponding CCI `ConnectionFactory`. The following listing shows the `InteractionCallback` interface definition: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5228,7 +4973,6 @@ The following listing shows the `InteractionCallback` interface definition: } ---- -==== NOTE: `InteractionSpec` objects can either be shared across multiple template calls or be newly created inside every callback method. This is completely up to the DAO implementation. @@ -5243,7 +4987,6 @@ ECI mode, with the IBM CICS ECI connector. First, we must do some initializations on the CCI `InteractionSpec` to specify which CICS program to access and how to interact with it, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5251,12 +4994,10 @@ CICS program to access and how to interact with it, as the following example sho interactionSpec.setFunctionName("MYPROG"); interactionSpec.setInteractionVerb(ECIInteractionSpec.SYNC_SEND_RECEIVE); ---- -==== Then the program can use CCI through Spring's template and specify mappings between custom objects and CCI `Records`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5285,12 +5026,10 @@ objects and CCI `Records`, as the following example shows: } } ---- -==== As discussed previously, you can use callbacks to work directly on CCI connections or interactions. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5312,7 +5051,6 @@ interactions. The following example shows how to do so: } ---- -==== NOTE: With a `ConnectionCallback`, the `Connection` used is managed and closed by the `CciTemplate`, but the callback implementation must manage any interactions created on the @@ -5321,7 +5059,6 @@ connection. For a more specific callback, you can implement an `InteractionCallback`. If you do so, the passed-in `Interaction` is managed and closed by the `CciTemplate`. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5344,12 +5081,10 @@ For a more specific callback, you can implement an `InteractionCallback`. If you } ---- -==== For the preceding examples, the corresponding configuration of the involved Spring beans could resemble the following example in non-managed mode: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5368,12 +5103,10 @@ could resemble the following example in non-managed mode: ---- -==== In managed mode (that is, in a Java EE environment), the configuration could resemble the following example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5383,7 +5116,6 @@ the following example: ---- -==== @@ -5416,7 +5148,6 @@ an output record to an output object (record mapping): The following listing shows the signatures of these methods: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5438,13 +5169,11 @@ The following listing shows the signatures of these methods: } ---- -==== Thereafter, ito execute an EIS operation, you need to use a single `execute` method, passing in an application-level input object and receiving an application-level output object as the result. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5458,14 +5187,12 @@ output object as the result. The following example shows how to do so: ... } ---- -==== Contrary to the `CciTemplate` class, this `execute(..)` method does not have an `InteractionSpec` as an argument. Instead, the `InteractionSpec` is global to the operation. You must use the following constructor to instantiate an operation object with a specific `InteractionSpec`. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5473,7 +5200,6 @@ with a specific `InteractionSpec`. The following example shows how to do so: MyMappingRecordOperation eisOperation = new MyMappingRecordOperation(getConnectionFactory(), spec); ... ---- -==== [[cci-object-mapping-comm-area]] @@ -5488,7 +5214,6 @@ and output record type and provides two new methods to convert an input object i input COMMAREA and convert the output COMMAREA into an output object. The following listing shows the relevant method signatures: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5506,7 +5231,6 @@ listing shows the relevant method signatures: } ---- -==== [[cci-automatic-record-gen]] @@ -5553,7 +5277,6 @@ SQL request to execute. In the following example, we directly define the way to parameters of the request to a CCI record and the way to convert the CCI result record to an instance of the `Person` class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5588,14 +5311,12 @@ to an instance of the `Person` class: } } ---- -==== Then the application can execute the operation object, with the person identifier as an argument. Note that you could set up the operation object as a shared instance, as it is thread-safe. The following executes the operation object with the person identifier as an argument: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5608,11 +5329,9 @@ argument: } } ---- -==== The corresponding configuration of Spring beans could be as follows in non-managed mode: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5642,12 +5361,10 @@ The corresponding configuration of Spring beans could be as follows in non-manag ---- -==== In managed mode (that is, in a Java EE environment), the configuration could be as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5668,7 +5385,6 @@ follows: ---- -==== [[cci-objects-mapping-comm-area-example]] @@ -5680,7 +5396,6 @@ CICS with ECI mode with the IBM CICS ECI connector. First, we need to initialize the CCI `InteractionSpec` to specify which CICS program to access and how to interact with it, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5704,12 +5419,10 @@ to access and how to interact with it, as the following example shows: } ---- -==== We can then subclass the abstract `EciMappingOperation` class to specify mappings between custom objects and `Records`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5737,11 +5450,9 @@ between custom objects and `Records`, as the following example shows: } ---- -==== The corresponding configuration of Spring beans could be as follows in non-managed mode: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5760,12 +5471,10 @@ The corresponding configuration of Spring beans could be as follows in non-manag ---- -==== In managed mode (that is, in a Java EE environment), the configuration could be as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5775,7 +5484,6 @@ follows: ---- -==== @@ -5788,7 +5496,6 @@ There are essentially three options: none (for example, with the CICS EPI connec transactions (for example, with a CICS ECI connector), and global transactions (for example, with an IMS connector). The following example configures the global option: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5800,7 +5507,6 @@ with an IMS connector). The following example configures the global option: ---- -==== For global transactions, you can use Spring's generic transaction infrastructure to demarcate transactions, with `JtaTransactionManager` as the backend (delegating to the Java @@ -5813,7 +5519,6 @@ transaction demarcation methods. Spring's `CciLocalTransactionManager` executes local CCI transactions in a fashion that is fully compliant with Spring's generic `PlatformTransactionManager` abstraction. The following example configures a `CciLocalTransactionManager`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5824,7 +5529,6 @@ local CCI transactions in a fashion that is fully compliant with Spring's generi ---- -==== You can use both transaction strategies with any of Spring's transaction demarcation facilities, be it declarative or programmatic. This is a consequence of Spring's generic @@ -5879,7 +5583,6 @@ JavaMail features, such as MIME message support to the `MailSender` interface Assume that we have a business interface called `OrderManager`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5889,7 +5592,6 @@ Assume that we have a business interface called `OrderManager`, as the following } ---- -==== Further assume that we have a requirement stating that an email message with an order number needs to be generated and sent to a customer who placed the relevant order. @@ -5901,7 +5603,6 @@ order number needs to be generated and sent to a customer who placed the relevan The following example shows how to use `MailSender` and `SimpleMailMessage` to send an email when someone places an order: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5947,11 +5648,9 @@ email when someone places an order: } ---- -==== The following example shows the bean definitions for the preceding code: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -5970,7 +5669,6 @@ The following example shows the bean definitions for the preceding code: ---- -==== [[mail-usage-mime]] @@ -5980,7 +5678,6 @@ This section describes another implementation of `OrderManager` that uses the `M callback interface. In the following example, the `mailSender` property is of type `JavaMailSender` so that we are able to use the JavaMail `MimeMessage` class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6028,7 +5725,6 @@ callback interface. In the following example, the `mailSender` property is of ty } ---- -==== NOTE: The mail code is a crosscutting concern and could well be a candidate for refactoring into a <>, which then could be executed at appropriate @@ -6047,7 +5743,6 @@ A class that comes in pretty handy when dealing with JavaMail messages is having to use the verbose JavaMail API. Using the `MimeMessageHelper`, it is pretty easy to create a `MimeMessage`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6062,7 +5757,6 @@ to create a `MimeMessage`, as the following example shows: sender.send(message); ---- -==== [[mail-javamail-mime-attachments]] @@ -6078,7 +5772,6 @@ that you do not want displayed as an attachment. The following example shows you how to use the `MimeMessageHelper` to send an email with a single JPEG image attachment: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6099,7 +5792,6 @@ with a single JPEG image attachment: sender.send(message); ---- -==== [[mail-javamail-mime-attachments-inline]] ===== Inline Resources @@ -6107,7 +5799,6 @@ with a single JPEG image attachment: The following example shows you how to use the `MimeMessageHelper` to send an email with an inline image: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6129,7 +5820,6 @@ with an inline image: sender.send(message); ---- -==== WARNING: Inline resources are added to the `MimeMessage` by using the specified `Content-ID` (`identifier1234` in the above example). The order in which you add the text @@ -6248,7 +5938,6 @@ Spring's `TaskExecutor` implementations are used as simple JavaBeans. In the fol we define a bean that uses the `ThreadPoolTaskExecutor` to asynchronously print out a set of messages: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6282,7 +5971,6 @@ out a set of messages: } } ---- -==== As you can see, rather than retrieving a thread from the pool and executing it yourself, you add your `Runnable` to the queue. Then the `TaskExecutor` uses its internal rules to @@ -6290,7 +5978,6 @@ decide when the task gets executed. To configure the rules that the `TaskExecutor` uses, we expose simple bean properties: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6304,7 +5991,6 @@ To configure the rules that the `TaskExecutor` uses, we expose simple bean prope ---- -==== @@ -6315,7 +6001,6 @@ In addition to the `TaskExecutor` abstraction, Spring 3.0 introduced a `TaskSche with a variety of methods for scheduling tasks to run at some point in the future. The following listing shows the `TaskScheduler` interface definition: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6344,7 +6029,6 @@ The following listing shows the `TaskScheduler` interface definition: ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay); } ---- -==== The simplest method is the one named `schedule` that takes only a `Runnable` and a `Date`. That causes the task to run once after the specified time. All of the other methods @@ -6363,7 +6047,6 @@ If these determinations do take into account the outcome of the preceding execut that information is available within a `TriggerContext`. The `Trigger` interface itself is quite simple, as the following listing shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6372,14 +6055,12 @@ is quite simple, as the following listing shows: Date nextExecutionTime(TriggerContext triggerContext); } ---- -==== The `TriggerContext` is the most important part. It encapsulates all of the relevant data and is open for extension in the future, if necessary. The `TriggerContext` is an interface (a `SimpleTriggerContext` implementation is used by default). The following listing shows the available methods for `Trigger` implementations. -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6392,7 +6073,6 @@ default). The following listing shows the available methods for `Trigger` implem Date lastCompletionTime(); } ---- -==== [[scheduling-trigger-implementations]] @@ -6403,13 +6083,11 @@ is the `CronTrigger`. It enables the scheduling of tasks based on cron expressio example, the following task is scheduled to run 15 minutes past each hour but only during the 9-to-5 "`business hours`" on weekdays: -==== [source,java,indent=0] [subs="verbatim"] ---- scheduler.schedule(task, new CronTrigger("0 15 9-17 * * MON-FRI")); ---- -==== The other implementation is a `PeriodicTrigger` that accepts a fixed period, an optional initial delay value, and a boolean to indicate whether the period @@ -6458,7 +6136,6 @@ execution. To enable support for `@Scheduled` and `@Async` annotations, you can add `@EnableScheduling` and `@EnableAsync` to one of your `@Configuration` classes, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6468,7 +6145,6 @@ To enable support for `@Scheduled` and `@Async` annotations, you can add `@Enabl public class AppConfig { } ---- -==== You can pick and choose the relevant annotations for your application. For example, if you need only support for `@Scheduled`, you can omit `@EnableAsync`. For more @@ -6481,7 +6157,6 @@ javadoc for full details. If you prefer XML configuration, you can use the `` element, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6489,7 +6164,6 @@ as the following example shows: ---- -==== Note that, with the preceding XML, an executor reference is provided for handling those tasks that correspond to methods with the `@Async` annotation, and the scheduler @@ -6509,7 +6183,6 @@ example, the following method is invoked every five seconds with a fixed delay, meaning that the period is measured from the completion time of each preceding invocation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6518,13 +6191,11 @@ invocation: // something that should execute periodically } ---- -==== If you need a fixed-rate execution, you can change the property name specified within the annotation. The following method is invoked every five seconds (measured between the successive start times of each invocation): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6533,13 +6204,11 @@ successive start times of each invocation): // something that should execute periodically } ---- -==== For fixed-delay and fixed-rate tasks, you can specify an initial delay by indicating the number of milliseconds to wait before the first execution of the method, as the following `fixedRate` example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6548,12 +6217,10 @@ number of milliseconds to wait before the first execution of the method, as the // something that should execute periodically } ---- -==== If simple periodic scheduling is not expressive enough, you ca provide a cron expression. For example, the following executes only on weekdays: -==== [source,java,indent=0] [subs="verbatim"] ---- @@ -6562,7 +6229,6 @@ For example, the following executes only on weekdays: // something that should execute on weekdays only } ---- -==== TIP: You can also use the `zone` attribute to specify the time zone in which the cron expression is resolved. @@ -6594,7 +6260,6 @@ invocation, while the actual execution of the method occurs in a task that has b submitted to a Spring `TaskExecutor`. In the simplest case, you can apply the annotation to a method that returns `void`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6603,14 +6268,12 @@ to a method that returns `void`, as the following example shows: // this will be executed asynchronously } ---- -==== Unlike the methods annotated with the `@Scheduled` annotation, these methods can expect arguments, because they are invoked in the "`normal`" way by callers at runtime rather than from a scheduled task being managed by the container. For example, the following code is a legitimate application of the `@Async` annotation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6619,7 +6282,6 @@ a legitimate application of the `@Async` annotation: // this will be executed asynchronously } ---- -==== Even methods that return a value can be invoked asynchronously. However, such methods are required to have a `Future`-typed return value. This still provides the benefit of @@ -6627,7 +6289,6 @@ asynchronous execution so that the caller can perform other tasks prior to calli `get()` on that `Future`. The following example shows how to use `@Async` on a method that returns a value: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6636,7 +6297,6 @@ that returns a value: // this will be executed asynchronously } ---- -==== TIP: `@Async` methods may not only declare a regular `java.util.concurrent.Future` return type but also Spring's `org.springframework.util.concurrent.ListenableFuture` or, as of Spring @@ -6648,7 +6308,6 @@ You can not use `@Async` in conjunction with lifecycle callbacks such as a separate initializing Spring bean that then invokes the `@Async` annotated method on the target, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6676,7 +6335,6 @@ target, as the following example shows: } ---- -==== NOTE: There is no direct XML equivalent for `@Async`, since such methods should be designed for asynchronous execution in the first place, not externally re-declared to be asynchronous. @@ -6694,7 +6352,6 @@ implementation, if any. However, you can use the `value` attribute of the `@Asyn annotation when you need to indicate that an executor other than the default should be used when executing a given method. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6703,7 +6360,6 @@ used when executing a given method. The following example shows how to do so: // this will be executed asynchronously by "otherExecutor" } ---- -==== In this case, `"otherExecutor"` can be the name of any `Executor` bean in the Spring container, or it may be the name of a qualifier associated with any `Executor` (for example, as @@ -6720,7 +6376,6 @@ however, the exception is uncaught and cannot be transmitted. You can provide an `AsyncUncaughtExceptionHandler` to handle such exceptions. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6732,7 +6387,6 @@ how to do so: } } ---- -==== By default, the exception is merely logged. You can define a custom `AsyncUncaughtExceptionHandler` by using `AsyncConfigurer` or the `` XML element. @@ -6753,13 +6407,11 @@ scheduled with a trigger. The following element creates a `ThreadPoolTaskScheduler` instance with the specified thread pool size: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== The value provided for the `id` attribute is used as the prefix for thread names within the pool. The `scheduler` element is relatively straightforward. If you do not @@ -6772,13 +6424,11 @@ There are no other configuration options for the scheduler. The following creates a `ThreadPoolTaskExecutor` instance: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== As with the scheduler shown in the <>, the value provided for the `id` attribute is used as the prefix for thread names within the pool. As far as the pool size is concerned, the @@ -6790,7 +6440,6 @@ has a fixed-size thread pool (the core and max sizes are the same). However, the `executor` element's `pool-size` attribute also accepts a range in the form of `min-max`. The following example sets a minimum value of `5` and a maximum value of `25`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6799,7 +6448,6 @@ The following example sets a minimum value of `5` and a maximum value of `25`: pool-size="5-25" queue-capacity="100"/> ---- -==== In the preceding configuration, a `queue-capacity` value has also been provided. The configuration of the thread pool should also be considered in light of the @@ -6842,7 +6490,6 @@ element. The following example shows an `executor` element with a number of attributes to specify various behaviors: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6852,7 +6499,6 @@ various behaviors: queue-capacity="100" rejection-policy="CALLER_RUNS"/> ---- -==== Finally, the `keep-alive` setting determines the time limit (in seconds) for which threads may remain idle before being terminated. If there are more than the core number of threads @@ -6861,7 +6507,6 @@ threads get terminated. A time value of zero causes excess threads to terminate immediately after executing a task without remaining follow-up work in the task queue. The following example sets the `keep-alive` value to two minutes: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6870,7 +6515,6 @@ The following example sets the `keep-alive` value to two minutes: pool-size="5-25" keep-alive="120"/> ---- -==== [[scheduling-task-namespace-scheduled-tasks]] @@ -6883,7 +6527,6 @@ for configuring message-driven POJOs. Basically, a `ref` attribute can point to Spring-managed object, and the `method` attribute provides the name of a method to be invoked on that object. The following listing shows a simple example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6893,7 +6536,6 @@ invoked on that object. The following listing shows a simple example: ---- -==== The scheduler is referenced by the outer element, and each individual task includes the configuration of its trigger metadata. In the preceding example, that @@ -6905,7 +6547,6 @@ any previous execution takes. Additionally, for both `fixed-delay` and `fixed-ra before the first execution of the method. For more control, you can instead provide a `cron` attribute. The following example shows these other options: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -6917,7 +6558,6 @@ The following example shows these other options: ---- -==== @@ -6937,7 +6577,6 @@ Quartz `JobDetail` objects contain all the information needed to run a job. Spri `JobDetailFactoryBean`, which provides bean-style properties for XML configuration purposes. Consider the following example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -6950,7 +6589,6 @@ Consider the following example: ---- -==== The job detail configuration has all the information it needs to run the job (`ExampleJob`). The timeout is specified in the job data map. The job data map is available through the @@ -6959,7 +6597,6 @@ its properties from the job data mapped to properties of the job instance. So, i the `ExampleJob` contains a bean property named `timeout`, and the `JobDetail` has it applied automatically: -==== [source,java,indent=0] [subs="verbatim"] ---- @@ -6983,7 +6620,6 @@ has it applied automatically: } ---- -==== All additional properties from the job data map are available to you as well. @@ -6998,7 +6634,6 @@ of the `JobDetailFactoryBean` (`exampleJob` in the preceding example above). Often you merely need to invoke a method on a specific object. By using the `MethodInvokingJobDetailFactoryBean`, you can do exactly this, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -7007,12 +6642,10 @@ Often you merely need to invoke a method on a specific object. By using the ---- -==== The preceding example results in the `doIt` method being called on the `exampleBusinessObject` method, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7031,7 +6664,6 @@ The preceding example results in the `doIt` method being called on the ---- ---- -==== By using the `MethodInvokingJobDetailFactoryBean`, you need not create one-line jobs that merely invoke a method. You need only create the actual business object and @@ -7045,7 +6677,6 @@ job does not start before the first one has finished. To make jobs resulting fro `MethodInvokingJobDetailFactoryBean` be non-concurrent, set the `concurrent` flag to `false`, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -7055,7 +6686,6 @@ job does not start before the first one has finished. To make jobs resulting fro ---- -==== NOTE: By default, jobs will run in a concurrent fashion. @@ -7076,7 +6706,6 @@ those triggers. The following listing uses both a `SimpleTriggerFactoryBean` and a `CronTriggerFactoryBean`: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -7095,13 +6724,11 @@ The following listing uses both a `SimpleTriggerFactoryBean` and a `CronTriggerF ---- -==== The preceding example sets up two triggers, one running every 50 seconds with a starting delay of 10 seconds and one running every morning at 6 AM. To finalize everything, we need to set up the `SchedulerFactoryBean`, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -7114,7 +6741,6 @@ seconds and one running every morning at 6 AM. To finalize everything, we need t ---- -==== More properties are available for the `SchedulerFactoryBean`, such as the calendars used by the job details, properties to customize Quartz with, and others. See the @@ -7234,14 +6860,12 @@ is, methods for which the result is stored in the cache so that, on subsequent i execute the method. In its simplest form, the annotation declaration requires the name of the cache associated with the annotated method, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @Cacheable("books") public Book findBook(ISBN isbn) {...} ---- -==== In the preceding snippet, the `findBook` method is associated with the cache named `books`. Each time the method is called, the cache is checked to see whether the invocation has @@ -7256,14 +6880,12 @@ the cached method was not actually executed. The following example uses `@Cacheable` on the `findBook` method: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @Cacheable({"books", "isbns"}) public Book findBook(ISBN isbn) {...} ---- -==== [[cache-annotations-cacheable-default-key]] ===== Default Key Generation @@ -7304,14 +6926,12 @@ that cannot be readily mapped on top of the cache structure. This tends to becom when the target method has multiple arguments out of which only some are suitable for caching (while the rest are used only by the method logic). Consider the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @Cacheable("books") public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) ---- -==== At first glance, while the two `boolean` arguments influence the way the book is found, they are no use for the cache. Furthermore, what if only one of the two is important @@ -7329,7 +6949,6 @@ work for some methods, it rarely works for all methods. The following examples ise various SpEL declarations (if you are not familiar with SpEL, do yourself a favor and read <>): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7342,7 +6961,6 @@ do yourself a favor and read < @Cacheable(cacheNames="books", **key="T(someType).hash(#isbn)"**) public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) ---- -==== The preceding snippets show how easy it is to select a certain argument, one of its properties, or even an arbitrary (static) method. @@ -7351,14 +6969,12 @@ If the algorithm responsible for generating the key is too specific or if it nee to be shared, you can define a custom `keyGenerator` on the operation. To do so, specify the name of the `KeyGenerator` bean implementation to use, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @Cacheable(cacheNames="books", **keyGenerator="myKeyGenerator"**) public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) ---- -==== NOTE: The `key` and `keyGenerator` parameters are mutually exclusive and an operation that specifies both results in an exception. @@ -7382,7 +6998,6 @@ single `CacheManager` and have no complex cache resolution requirements. For applications that work with several cache managers, you can set the `cacheManager` to use for each operation, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7390,7 +7005,7 @@ set the `cacheManager` to use for each operation, as the following example shows public Book findBook(ISBN isbn) {...} ---- <1> Specifying `anotherCacheManager`. -==== + You can also replace the `CacheResolver` entirely in a fashion similar to that of replacing <>. The @@ -7398,7 +7013,6 @@ resolution is requested for every cache operation, letting the implementation actually resolve the caches to use based on runtime arguments. The following example shows how to specify a `CacheResolver`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7406,7 +7020,7 @@ runtime arguments. The following example shows how to specify a `CacheResolver`: public Book findBook(ISBN isbn) {...} ---- <1> Specifying the `CacheResolver`. -==== + [NOTE] ==== @@ -7433,7 +7047,6 @@ cache provider to lock the cache entry while the value is being computed. As a r only one thread is busy computing the value, while the others are blocked until the entry is updated in the cache. The following example shows how to use the `sync` attribute: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7441,7 +7054,7 @@ entry is updated in the cache. The following example shows how to use the `sync` public Foo executeExpensiveOperation(String id) {...} ---- <1> Using the `sync` attribute. -==== + NOTE: This is an optional feature, and your favorite cache library may not support it. All `CacheManager` implementations provided by the core framework support it. See the @@ -7458,7 +7071,6 @@ method is not cached (that is, the method is executed every time no matter what or what arguments are used). For example, the following method is cached only if the argument `name` has a length shorter than 32: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7466,14 +7078,13 @@ if the argument `name` has a length shorter than 32: public Book findBook(String name) ---- <1> Setting a condition on `@Cacheable`. -==== + In addition to the `condition` parameter, you can use the `unless` parameter to veto the adding of a value to the cache. Unlike `condition`, `unless` expressions are evaluated after the method has been called. To expand on the previous example, perhaps we only want to cache paperback books, as the following example does: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7481,20 +7092,18 @@ only want to cache paperback books, as the following example does: public Book findBook(String name) ---- <1> Using the `unless` attribute to block hardbacks. -==== + The cache abstraction supports `java.util.Optional`, using its content as the cached value only if it is present. `#result` always refers to the business entity and never a supported wrapper, so the previous example can be rewritten as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @Cacheable(cacheNames="book", condition="#name.length() < 32", **unless="#result?.hardback"**) public Optional findBook(String name) ---- -==== Note that `result` still refers to `Book` and not `Optional`. As it might be `null`, we should use the safe navigation operator. @@ -7600,7 +7209,6 @@ condition to be specified, and features an extra parameter rather then just an entry eviction (based on the key). The following example evicts all entries from the `books` cache: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7608,7 +7216,7 @@ all entries from the `books` cache: public void loadBooks(InputStream batch) ---- <1> Using the `allEntries` attribute to evict all entries from the cache. -==== + This option comes in handy when an entire cache region needs to be cleared out. Rather then evicting each entry (which would take a long time, since it is inefficient), all the @@ -7640,14 +7248,12 @@ expression is different between different caches. `@Caching` lets multiple neste `@Cacheable`, `@CachePut`, and `@CacheEvict` annotations be used on the same method. The following example uses two `@CacheEvict` annotations: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") }) public Book importBooks(String deposit, Date date) ---- -==== [[cache-annotations-config]] @@ -7660,7 +7266,6 @@ instance, specifying the name of the cache to use for every cache operation of t class can be replaced by a single class-level definition. This is where `@CacheConfig` comes into play. The following examples uses `@CacheConfig` to set the name of the cache: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7672,7 +7277,7 @@ comes into play. The following examples uses `@CacheConfig` to set the name of t } ---- <1> Using `@CacheConfig` to set the name of the cache. -==== + `@CacheConfig` is a class-level annotation that allows sharing the cache names, the custom `KeyGenerator`, the custom `CacheManager`, and the custom `CacheResolver`. Placing @@ -7709,7 +7314,6 @@ To enable caching annotations add the annotation `@EnableCaching` to one of your Alternatively, for XML configuration you can use the `cache:annotation-driven` element: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -7723,7 +7327,6 @@ Alternatively, for XML configuration you can use the `cache:annotation-driven` e ---- -==== Both the `cache:annotation-driven` element and the `@EnableCaching` annotation let you specify various options that influence the way the caching behavior is added to the @@ -7859,7 +7462,6 @@ not allowed in your code base. Similarly to the rest of the (that is, annotations that can annotate other annotations). In the following example, we replace a common `@Cacheable` declaration with our own custom annotation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7869,31 +7471,26 @@ not allowed in your code base. Similarly to the rest of the public @interface SlowService { } ---- -==== In the preceding example, we have defined our own `SlowService` annotation, which itself is annotated with `@Cacheable`. Now we can replace the following code: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @Cacheable(cacheNames="books", key="#isbn") public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) ---- -==== The following example shows the custom annotation with which we can replace the preceding code: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @SlowService public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed) ---- -==== Even though `@SlowService` is not a Spring annotation, the container automatically picks up its declaration at runtime and understands its meaning. Note that, as mentioned @@ -7963,7 +7560,6 @@ javadoc of `@CacheResult#cacheName()` for more information. `CacheResolver` instances are retrieved by a `CacheResolverFactory`. It is possible to customize the factory for each cache operation, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7971,7 +7567,7 @@ possible to customize the factory for each cache operation, as the following exa public Book findBook(ISBN isbn) ---- <1> Customizing the factory for this operation. -==== + NOTE: For all referenced classes, Spring tries to locate a bean with the given type. If more than one match exists, a new instance is created and can use the regular @@ -7984,7 +7580,6 @@ similar to Spring's <>. For instance, the following are identical operations, one using Spring's abstraction and the other using JCache: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -7994,7 +7589,6 @@ abstraction and the other using JCache: @CacheResult(cacheName="books") public Book findBook(**@CacheKey** ISBN isbn, boolean checkWarehouse, boolean includeUsed) ---- -==== You can also specify the `CacheKeyResolver` on the operation, similar to how you can specify the `CacheResolverFactory`. @@ -8007,7 +7601,6 @@ retrieved with such a parameter). The following caches the exception so that fur with the same, invalid, ISBN throw the cached exception directly instead of invoking the method again: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -8015,7 +7608,6 @@ the method again: **cachedExceptions = InvalidIsbnNotFoundException.class**) public Book findBook(ISBN isbn) ---- -==== ==== Enabling JSR-107 support @@ -8042,7 +7634,6 @@ specify the target method and the caching directives externally (similar to the declarative transaction management <>). The example from the previous section can be translated into the following example: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -8064,7 +7655,6 @@ The example from the previous section can be translated into the following examp ---- -==== In the preceding configuration, the `bookService` is made cacheable. The caching semantics to apply are encapsulated in the `cache:advice` definition, which causes the @@ -8139,7 +7729,6 @@ The Ehcache 2.x implementation is located in the `org.springframework.cache.ehca Again, to use it, you need to declare the appropriate `CacheManager`. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -8150,7 +7739,6 @@ example shows how to do so: ---- -==== This setup bootstraps the ehcache library inside the Spring IoC (through the `ehcache` bean), which is then wired into the dedicated `CacheManager` implementation. Note that the entire @@ -8166,19 +7754,16 @@ of Caffeine. The following example configures a `CacheManager` that creates the cache on demand: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== You can also provide the caches to use explicitly. In that case, only those are made available by the manager. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -8191,7 +7776,6 @@ are made available by the manager. The following example shows how to do so: ---- -==== The Caffeine `CacheManager` also supports custom `Caffeine` and `CacheLoader`. See the https://github.com/ben-manes/caffeine/wiki[Caffeine documentation] for more @@ -8217,7 +7801,6 @@ implementation is located in the `org.springframework.cache.jcache` package. Again, to use it, you need to declare the appropriate `CacheManager`. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -8228,7 +7811,6 @@ example shows how to do so: ---- -==== [[cache-store-configuration-noop]] @@ -8242,7 +7824,6 @@ cache declarations (which can prove tedious), you can wire in a simple dummy cac performs no caching -- that is, it forces the cached methods to be executed every time. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -8256,7 +7837,6 @@ The following example shows how to do so: ---- -==== The `CompositeCacheManager` in the preceding chains multiple `CacheManager` instances and, through the `fallbackToNoOpCache` flag, adds a no-op cache for all the diff --git a/src/docs/asciidoc/languages/dynamic-languages.adoc b/src/docs/asciidoc/languages/dynamic-languages.adoc index c2544c02f1..dcc12969cd 100644 --- a/src/docs/asciidoc/languages/dynamic-languages.adoc +++ b/src/docs/asciidoc/languages/dynamic-languages.adoc @@ -42,7 +42,6 @@ Note that this interface is defined in plain Java. Dependent objects that are injected with a reference to the `Messenger` do not know that the underlying implementation is a Groovy script. The following listing shows the `Messenger` interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -54,11 +53,9 @@ implementation is a Groovy script. The following listing shows the `Messenger` i } ---- -==== The following example defines a class that has a dependency on the `Messenger` interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -78,11 +75,9 @@ The following example defines a class that has a dependency on the `Messenger` i } ---- -==== The following example implements the `Messenger` interface in Groovy: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -99,7 +94,6 @@ The following example implements the `Messenger` interface in Groovy: } ---- -==== [NOTE] ==== @@ -118,7 +112,6 @@ Finally, the following example shows the bean definitions that effect the inject Groovy-defined `Messenger` implementation into an instance of the `DefaultBookingService` class: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -141,7 +134,6 @@ Groovy-defined `Messenger` implementation into an instance of the ---- -==== The `bookingService` bean (a `DefaultBookingService`) can now use its private `messenger` member variable as normal, because the `Messenger` instance that was injected @@ -244,7 +236,6 @@ So, if we stick with <> from earli chapter, the following example shows what we would change in the Spring XML configuration to effect refreshable beans: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -263,7 +254,6 @@ refreshable beans: ---- -==== That really is all you have to do. The `refresh-check-delay` attribute defined on the `messenger` bean definition is the number of milliseconds after which the bean is @@ -281,7 +271,6 @@ the program resumes execution. The following listing shows this sample application: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -301,14 +290,12 @@ The following listing shows this sample application: } } ---- -==== Assume then, for the purposes of this example, that all calls to the `getMessage()` method of `Messenger` implementations have to be changed such that the message is surrounded by quotation marks. The following listing shows the changes that you (the developer) should make to the `Messenger.groovy` source file when the execution of the program is paused: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -328,7 +315,6 @@ message is surrounded by quotation marks. The following listing shows the change } } ---- -==== When the program runs, the output before the input pause will be `I Can Do The Frug`. After the change to the source file is made and saved and the program resumes @@ -363,7 +349,6 @@ embedded directly in Spring bean definitions. More specifically, the inside a Spring configuration file. An example might clarify how the inline script feature works: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -382,7 +367,6 @@ feature works: ---- -==== If we put to one side the issues surrounding whether it is good practice to define dynamic language source inside a Spring configuration file, the `` @@ -404,7 +388,6 @@ constructors and properties 100% clear, the following mixture of code and config does not work: .An approach that cannot work -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -443,7 +426,6 @@ does not work: ---- -==== In practice this limitation is not as significant as it first appears, since setter injection is the injection style favored by the overwhelming majority of developers @@ -477,7 +459,6 @@ If you have read this chapter straight from the top, you have already <> of a Groovy-dynamic-language-backed bean. Now consider another example (again using an example from the Spring test suite): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -489,11 +470,9 @@ bean. Now consider another example (again using an example from the Spring test } ---- -==== The following example implements the `Calculator` interface in Groovy: -==== [source,groovy,indent=0] [subs="verbatim,quotes"] ---- @@ -508,11 +487,9 @@ The following example implements the `Calculator` interface in Groovy: } ---- -==== The following bean definition uses the calculator defined in Groovy: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -521,11 +498,9 @@ The following bean definition uses the calculator defined in Groovy: ---- -==== Finally, the following small application exercises the preceding configuration: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -543,7 +518,6 @@ Finally, the following small application exercises the preceding configuration: } } ---- -==== The resulting output from running the above program is (unsurprisingly) `10`. (For more interesting examples, @@ -566,7 +540,6 @@ implementations of this interface could invoke any required initialization metho set some default property values, or specify a custom `MetaClass`. The following listing shows the `GroovyObjectCustomizer` interface definition: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -575,7 +548,6 @@ shows the `GroovyObjectCustomizer` interface definition: void customize(GroovyObject goo); } ---- -==== The Spring Framework instantiates an instance of your Groovy-backed bean and then passes the created `GroovyObject` to the specified `GroovyObjectCustomizer` (if one @@ -583,7 +555,6 @@ has been defined). You can do whatever you like with the supplied `GroovyObject` reference. We expect that most people want to set a custom `MetaClass` with this callback, and the following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -603,7 +574,6 @@ and the following example shows how to do so: } ---- -==== A full discussion of meta-programming in Groovy is beyond the scope of the Spring reference manual. See the relevant section of the Groovy reference manual or do a @@ -611,7 +581,6 @@ search online. Plenty of articles address this topic. Actually, making use of a `GroovyObjectCustomizer` is easy if you use the Spring namespace support, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -623,12 +592,10 @@ following example shows: script-source="classpath:org/springframework/scripting/groovy/Calculator.groovy" customizer-ref="tracingCustomizer"/> ---- -==== If you do not use the Spring namespace support, you can still use the `GroovyObjectCustomizer` functionality, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -642,7 +609,6 @@ If you do not use the Spring namespace support, you can still use the ---- -==== NOTE: As of Spring Framework 4.3.3, you may also specify a Groovy `CompilationCustomizer` (such as an `ImportCustomizer`) or even a full Groovy `CompilerConfiguration` object @@ -684,7 +650,6 @@ Now we can show a fully working example of using a BeanShell-based bean that imp the `Messenger` interface that was defined earlier in this chapter. We again show the definition of the `Messenger` interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -696,12 +661,10 @@ definition of the `Messenger` interface: } ---- -==== The following example shows the BeanShell "`implementation`" (we use the term loosely here) of the `Messenger` interface: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -715,12 +678,10 @@ The following example shows the BeanShell "`implementation`" (we use the term lo message = aMessage; } ---- -==== The following example shows the Spring XML that defines an "`instance`" of the above "`class`" (again, we use these terms very loosely here): -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -730,7 +691,6 @@ we use these terms very loosely here): ---- -==== See <> for some scenarios where you might want to use BeanShell-based beans. @@ -773,7 +733,6 @@ beans, you have to enable the "`refreshable beans`" functionality. See The following example shows an `org.springframework.web.servlet.mvc.Controller` implemented by using the Groovy dynamic language: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -809,7 +768,6 @@ by using the Groovy dynamic language: ---- -==== @@ -836,7 +794,6 @@ by using the Groovy dynamic language (see <> for a discussion of the `Validator` interface): -==== [source,groovy,indent=0] [subs="verbatim,quotes"] ---- @@ -859,7 +816,6 @@ Validation using Spring’s Validator interface>> for a discussion of the } ---- -==== @@ -899,7 +855,6 @@ with "`regular`" beans.) The following example uses the `scope` attribute to define a Groovy bean scoped as a <>: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -920,7 +875,6 @@ a <>: ---- -==== See <> in <> for a full discussion of the scoping support in the Spring Framework. @@ -943,7 +897,6 @@ the following preamble at the top of your Spring XML configuration file. The tex following snippet references the correct schema so that the tags in the `lang` namespace are available to you: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -958,7 +911,6 @@ are available to you: ---- -==== diff --git a/src/docs/asciidoc/languages/kotlin.adoc b/src/docs/asciidoc/languages/kotlin.adoc index b3c61b4b11..53af2faafe 100644 --- a/src/docs/asciidoc/languages/kotlin.adoc +++ b/src/docs/asciidoc/languages/kotlin.adoc @@ -56,23 +56,19 @@ for their APIs, thus giving a better Kotlin development experience overall. To retrieve a list of `User` objects in Java, you would normally write the following: -==== [source,java,indent=0] ---- Flux users = client.get().retrieve().bodyToFlux(User.class) ---- -==== With Kotlin and the Spring Framework extensions, you can instead write the following: -==== [source,kotlin,indent=0] ---- val users = client.get().retrieve().bodyToFlux() // or (both are equivalent) val users : Flux = client.get().retrieve().bodyToFlux() ---- -==== As in Java, `users` in Kotlin is strongly typed, but Kotlin's clever type inference allows for shorter syntax. @@ -176,7 +172,6 @@ This mechanism is very efficient, as it does not require any reflection or CGLIB In Java, you can, for example, write the following: -==== [source,java,indent=0] ---- GenericApplicationContext context = new GenericApplicationContext(); @@ -184,12 +179,10 @@ In Java, you can, for example, write the following: context.registerBean(Bar.class, () -> new Bar(context.getBean(Foo.class)) ); ---- -==== In Kotlin, with reified type parameters and `GenericApplicationContext` Kotlin extensions, you can instead write the following: -==== [source,kotlin,indent=0] ---- val context = GenericApplicationContext().apply { @@ -197,7 +190,6 @@ Kotlin extensions, you can instead write the following: registerBean { Bar(it.getBean()) } } ---- -==== In order to allow a more declarative approach and cleaner syntax, Spring Framework provides a {doc-root}/spring-framework/docs/{spring-version}/kdoc-api/spring-framework/org.springframework.context.support/-bean-definition-dsl/[Kotlin bean definition DSL] @@ -205,7 +197,6 @@ It declares an `ApplicationContextInitializer` through a clean declarative API, which lets you deal with profiles and `Environment` for customizing how beans are registered. The following example creates a `Play` profile: -==== [source,kotlin,indent=0] ---- fun beans() = beans { @@ -237,7 +228,6 @@ how beans are registered. The following example creates a `Play` profile: } } ---- -==== In the preceding example, `bean()` uses autowiring by constructor, and `ref()` is a shortcut for `applicationContext.getBean(Routes::class.java)`. @@ -245,7 +235,6 @@ is a shortcut for `applicationContext.getBean(Routes::class.java)`. You can then use this `beans()` function to register beans on the application context, as the following example shows: -==== [source,kotlin,indent=0] ---- val context = GenericApplicationContext().apply { @@ -253,7 +242,6 @@ as the following example shows: refresh() } ---- -==== NOTE: This DSL is programmatic, meaning it allows custom registration logic of beans through an `if` expression, a `for` loop, or any other Kotlin constructs. @@ -281,7 +269,6 @@ Spring Framework now comes with a that lets you use the <> to write clean and idiomatic Kotlin code, as the following example shows: -==== [source,kotlin,indent=0] ---- router { @@ -301,7 +288,6 @@ API>> to write clean and idiomatic Kotlin code, as the following example shows: resources("/**", ClassPathResource("static/")) } ---- -==== NOTE: This DSL is programmatic, meaning that it allows custom registration logic of beans through an `if` expression, a `for` loop, or any other Kotlin constructs. That can be useful when you need to register routes @@ -330,7 +316,6 @@ https://github.com/Kotlin/kotlinx.html[kotlinx.html] DSL or by a using Kotlin mu This can let you write Kotlin templates with full autocompletion and refactoring support in a supported IDE, as the following example shows: -==== [source,kotlin,indent=0] ---- import io.spring.demo.* @@ -344,7 +329,6 @@ refactoring support in a supported IDE, as the following example shows: ${include("footer")} """ ---- -==== See the https://github.com/sdeleuze/kotlin-script-templating[kotlin-script-templating] example project for more details. @@ -399,12 +383,10 @@ you can write your Kotlin beans without any additional `open` keyword, as in Jav In Kotlin, it is convenient and considered to be a best practice to declare read-only properties within the primary constructor, as in the following example: -==== [source,kotlin,indent=0] ---- class Person(val name: String, val age: Int) ---- -==== You can optionally add https://kotlinlang.org/docs/reference/data-classes.html[the `data` keyword] to make the compiler automatically derive the following members from all properties declared @@ -417,7 +399,6 @@ in the primary constructor: As the following example shows, this allows for easy changes to individual properties, even if `Person` properties are read-only: -==== [source,kotlin,indent=0] ---- data class Person(val name: String, val age: Int) @@ -425,7 +406,6 @@ As the following example shows, this allows for easy changes to individual prope val jack = Person(name = "Jack", age = 1) val olderJack = jack.copy(age = 2) ---- -==== Common persistence technologies (such as JPA) require a default constructor, preventing this kind of design. Fortunately, there is now a workaround for this @@ -448,7 +428,6 @@ mappings (such as MongoDB, Redis, Cassandra, and others). Our recommendation is to try and favor constructor injection with `val` read-only (and non-nullable when possible) https://kotlinlang.org/docs/reference/properties.html[properties], as the following example shows: -==== [source,kotlin,indent=0] ---- @Component @@ -457,7 +436,6 @@ https://kotlinlang.org/docs/reference/properties.html[properties], as the follow private val solrClient: SolrClient ) ---- -==== NOTE: As of Spring Framework 4.3, classes with a single constructor have their parameters automatically autowired, that's why there is no need for an @@ -466,7 +444,6 @@ explicit `@Autowired constructor` in the example shown above. If you really need to use field injection, you can use the `lateinit var` construct, as the following example shows: -==== [source,kotlin,indent=0] ---- @Component @@ -479,7 +456,6 @@ as the following example shows: lateinit var solrClient: SolrClient } ---- -==== @@ -494,7 +470,6 @@ character by writing `@Value("\${property}")`. As an alternative, you can customize the properties placeholder prefix by declaring the following configuration beans: -==== [source,kotlin,indent=0] ---- @Bean @@ -502,12 +477,10 @@ the following configuration beans: setPlaceholderPrefix("%{") } ---- -==== You can customize existing code (such as Spring Boot actuators or `@LocalServerPort`) that uses the `${...}` syntax, with configuration beans, as the following example shows: -==== [source,kotlin,indent=0] ---- @Bean @@ -519,7 +492,6 @@ with configuration beans, as the following example shows: @Bean fun defaultPropertyConfigurer() = PropertySourcesPlaceholderConfigurer() ---- -==== NOTE: If you use Spring Boot, you can use https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-typesafe-configuration-properties[`@ConfigurationProperties`] @@ -543,7 +515,6 @@ specify it as a `vararg` parameter. To understand what that means, consider `@RequestMapping` (which is one of the most widely used Spring annotations) as an example. This Java annotation is declared as follows: -==== [source,java,indent=0] ---- public @interface RequestMapping { @@ -559,7 +530,6 @@ of the most widely used Spring annotations) as an example. This Java annotation // ... } ---- -==== The typical use case for `@RequestMapping` is to map a handler method to a specific path and method. In Java, you can specify a single value for the @@ -600,7 +570,6 @@ You can now change the default behavior to `PER_CLASS` thanks to a The following example `@BeforeAll` and `@AfterAll` annotations on non-static methods: -==== [source] ---- class IntegrationTests { @@ -630,7 +599,6 @@ class IntegrationTests { } } ---- -==== @@ -639,7 +607,6 @@ class IntegrationTests { You can create specification-like tests with JUnit 5 and Kotlin. The following example shows how to do so: -==== [source] ---- class SpecificationLikeTests { @@ -663,7 +630,6 @@ class SpecificationLikeTests { } } ---- -==== diff --git a/src/docs/asciidoc/testing-webtestclient.adoc b/src/docs/asciidoc/testing-webtestclient.adoc index c772dce04c..7607cb991b 100644 --- a/src/docs/asciidoc/testing-webtestclient.adoc +++ b/src/docs/asciidoc/testing-webtestclient.adoc @@ -27,13 +27,11 @@ a URL to connect to a running server. The following example shows how to create a server setup to test one `@Controller` at a time: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- client = WebTestClient.bindToController(new TestController()).build(); ---- -==== The preceding example loads the <> and registers the given controller. The resulting WebFlux application is tested @@ -48,14 +46,12 @@ on the builder to customize the default WebFlux Java configuration. The following example shows how to set up a server from a <>: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- RouterFunction route = ... client = WebTestClient.bindToRouterFunction(route).build(); ---- -==== Internally, the configuration is passed to `RouterFunctions.toWebHandler`. The resulting WebFlux application is tested without an HTTP server by using mock @@ -69,7 +65,6 @@ request and response objects. The following example shows how to setup a server from the Spring configuration of your application or some subset of it: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -92,7 +87,6 @@ some subset of it: <1> Specify the configuration to load <2> Inject the configuration <3> Create the `WebTestClient` -==== Internally, the configuration is passed to `WebHttpHandlerBuilder` to set up the request processing chain. See @@ -107,13 +101,11 @@ and response objects. The following server setup option lets you connect to a running server: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- client = WebTestClient.bindToServer().baseUrl("http://localhost:8080").build(); ---- -==== @@ -125,7 +117,6 @@ options, including base URL, default headers, client filters, and others. These are readily available following `bindToServer`. For all others, you need to use `configureClient()` to transition from server to client configuration, as follows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -134,7 +125,6 @@ are readily available following `bindToServer`. For all others, you need to use .baseUrl("/test") .build(); ---- -==== @@ -148,7 +138,6 @@ up to the point of performing a request by using `exchange()`. What follows afte Typically, you start by asserting the response status and headers, as follows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -159,7 +148,6 @@ Typically, you start by asserting the response status and headers, as follows: .expectHeader().contentType(MediaType.APPLICATION_JSON_UTF8) // ... ---- -==== Then you specify how to decode and consume the response body: @@ -169,7 +157,6 @@ Then you specify how to decode and consume the response body: Then you can use built-in assertions for the body. The following example shows one way to do so: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -178,11 +165,9 @@ Then you can use built-in assertions for the body. The following example shows o .expectStatus().isOk() .expectBodyList(Person.class).hasSize(3).contains(person); ---- -==== You can also go beyond the built-in assertions and create your own, as the following example shows: -==== ---- client.get().uri("/persons/1") .exchange() @@ -192,11 +177,9 @@ You can also go beyond the built-in assertions and create your own, as the follo // custom assertions (e.g. AssertJ)... }); ---- -==== You can also exit the workflow and get a result, as follows: -==== ---- EntityExchangeResult result = client.get().uri("/persons/1") .exchange() @@ -204,7 +187,6 @@ You can also exit the workflow and get a result, as follows: .expectBody(Person.class) .returnResult(); ---- -==== TIP: When you need to decode to a target type with generics, look for the overloaded methods that accept @@ -219,7 +201,6 @@ instead of `Class`. If the response has no content (or you do not care if it does) use `Void.class`, which ensures that resources are released. The following example shows how to do so: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -228,11 +209,9 @@ that resources are released. The following example shows how to do so: .expectStatus().isNotFound() .expectBody(Void.class); ---- -==== Alternatively, if you want to assert there is no response content, you can use code similar to the following: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -242,7 +221,6 @@ Alternatively, if you want to assert there is no response content, you can use c .expectStatus().isCreated() .expectBody().isEmpty(); ---- -==== @@ -253,7 +231,6 @@ When you use `expectBody()`, the response is consumed as a `byte[]`. This is use raw content assertions. For example, you can use http://jsonassert.skyscreamer.org[JSONAssert] to verify JSON content, as follows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -263,11 +240,9 @@ http://jsonassert.skyscreamer.org[JSONAssert] to verify JSON content, as follows .expectBody() .json("{\"name\":\"Jane\"}") ---- -==== You can also use https://github.com/jayway/JsonPath[JSONPath] expressions, as follows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -278,7 +253,6 @@ You can also use https://github.com/jayway/JsonPath[JSONPath] expressions, as fo .jsonPath("$[0].name").isEqualTo("Jane") .jsonPath("$[1].name").isEqualTo("Jason"); ---- -==== @@ -289,7 +263,6 @@ To test infinite streams (for example, `"text/event-stream"` or `"application/st you need to exit the chained API (by using `returnResult`), immediately after the response status and header assertions, as the following example shows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -300,13 +273,11 @@ and header assertions, as the following example shows: .returnResult(MyEvent.class); ---- -==== Now you can consume the `Flux`, assert decoded objects as they come, and then cancel at some point when test objectives are met. We recommend using the `StepVerifier` from the `reactor-test` module to do that, as the following example shows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -319,7 +290,6 @@ from the `reactor-test` module to do that, as the following example shows: .thenCancel() .verify(); ---- -==== diff --git a/src/docs/asciidoc/testing.adoc b/src/docs/asciidoc/testing.adoc index 36ba5b333d..b03ded52c1 100644 --- a/src/docs/asciidoc/testing.adoc +++ b/src/docs/asciidoc/testing.adoc @@ -443,7 +443,6 @@ classes can be component classes, and so on. The following example shows a `@ContextConfiguration` annotation that refers to an XML file: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -453,11 +452,10 @@ file: } ---- <1> Referring to an XML file. -==== + The following example shows a `@ContextConfiguration` annotation that refers to a class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -467,13 +465,12 @@ The following example shows a `@ContextConfiguration` annotation that refers to } ---- <1> Referring to a class. -==== + As an alternative or in addition to declaring resource locations or annotated classes, you can use `@ContextConfiguration` to declare `ApplicationContextInitializer` classes. The following example shows such a case: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -483,7 +480,7 @@ The following example shows such a case: } ---- <1> Declaring an initializer class. -==== + You can optionally use `@ContextConfiguration` to declare the `ContextLoader` strategy as well. Note, however, that you typically do not need to explicitly configure the loader, @@ -492,7 +489,6 @@ annotated `classes`. The following example uses both a location and a loader: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -502,7 +498,7 @@ The following example uses both a location and a loader: } ---- <1> Configuring both a location and a custom loader. -==== + NOTE: `@ContextConfiguration` provides support for inheriting resource locations or configuration classes as well as context initializers that are declared by superclasses. @@ -524,7 +520,6 @@ resource base path). The resource base path is used behind the scenes to create The following example shows how to use the `@WebAppConfiguration` annotation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -535,14 +530,13 @@ The following example shows how to use the `@WebAppConfiguration` annotation: } ---- <1> The `@WebAppConfiguration` annotation. -==== + To override the default, you can specify a different base resource path by using the implicit `value` attribute. Both `classpath:` and `file:` resource prefixes are supported. If no resource prefix is supplied, the path is assumed to be a file system resource. The following example shows how to specify a classpath resource: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -553,7 +547,7 @@ resource. The following example shows how to specify a classpath resource: } ---- <1> Specifying a classpath resource. -==== + Note that `@WebAppConfiguration` must be used in conjunction with `@ContextConfiguration`, either within a single test class or within a test class @@ -571,7 +565,6 @@ defines a level in the context hierarchy. The following examples demonstrate the `@ContextHierarchy` within a single test class (`@ContextHierarchy` can also be used within a test class hierarchy): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -596,7 +589,6 @@ within a test class hierarchy): // class body... } ---- -==== If you need to merge or override the configuration for a given level of the context hierarchy within a test class hierarchy, you must explicitly name that level by supplying @@ -614,7 +606,6 @@ integration test. The following example indicates that the `dev` profile should be active: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -625,12 +616,11 @@ The following example indicates that the `dev` profile should be active: } ---- <1> Indicate that the `dev` profile should be active. -==== + The following example indicates that both the `dev` and the `integration` profiles should be active: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -641,7 +631,7 @@ be active: } ---- <1> Indicate that the `dev` and `integration` profiles should be active. -==== + NOTE: `@ActiveProfiles` provides support for inheriting active bean definition profiles declared by superclasses by default. You can also resolve active bean definition profiles @@ -670,7 +660,6 @@ properties loaded from resource locations. The following example demonstrates how to declare a properties file from the classpath: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -681,11 +670,10 @@ The following example demonstrates how to declare a properties file from the cla } ---- <1> Get properties from `test.properties` in the root of the classpath. -==== + The following example demonstrates how to declare inlined properties: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -696,7 +684,7 @@ The following example demonstrates how to declare inlined properties: } ---- <1> Declare `timezone` and `port` properties. -==== + [[spring-testing-annotation-dirtiescontext]] ===== `@DirtiesContext` @@ -720,7 +708,6 @@ configuration scenarios: * Before the current test class, when declared on a class with class mode set to `BEFORE_CLASS`. + -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -730,12 +717,11 @@ configuration scenarios: } ---- <1> Dirty the context before the current test class. -==== + * After the current test class, when declared on a class with class mode set to `AFTER_CLASS` (i.e., the default class mode). + -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -745,12 +731,11 @@ configuration scenarios: } ---- <1> Dirty the context after the current test class. -==== + * Before each test method in the current test class, when declared on a class with class mode set to `BEFORE_EACH_TEST_METHOD.` + -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -760,12 +745,11 @@ mode set to `BEFORE_EACH_TEST_METHOD.` } ---- <1> Dirty the context before each test method. -==== + * After each test method in the current test class, when declared on a class with class mode set to `AFTER_EACH_TEST_METHOD.` + -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -775,12 +759,11 @@ mode set to `AFTER_EACH_TEST_METHOD.` } ---- <1> Dirty the context after each test method. -==== + * Before the current test, when declared on a method with the method mode set to `BEFORE_METHOD`. + -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -791,12 +774,11 @@ mode set to `AFTER_EACH_TEST_METHOD.` } ---- <1> Dirty the context before the current test method. -==== + * After the current test, when declared on a method with the method mode set to `AFTER_METHOD` (i.e., the default method mode). + -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -807,7 +789,7 @@ mode set to `AFTER_EACH_TEST_METHOD.` } ---- <1> Dirty the context after the current test method. -==== + If you use `@DirtiesContext` in a test whose context is configured as part of a context hierarchy with `@ContextHierarchy`, you can use the `hierarchyMode` flag to control how @@ -819,7 +801,6 @@ context are removed from the context cache and closed. If the exhaustive algorit overkill for a particular use case, you can specify the simpler current level algorithm, as the following example shows. -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -841,7 +822,7 @@ as the following example shows. } ---- <1> Use the current-level algorithm. -==== + For further details regarding the `EXHAUSTIVE` and `CURRENT_LEVEL` algorithms, see the {api-spring-framework}/test/annotation/DirtiesContext.HierarchyMode.html[`DirtiesContext.HierarchyMode`] @@ -857,7 +838,6 @@ javadoc. The following example shows how to register two `TestExecutionListener` implementations: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -868,7 +848,7 @@ The following example shows how to register two `TestExecutionListener` implemen } ---- <1> Register two `TestExecutionListener` implementations. -==== + By default, `@TestExecutionListeners` supports inherited listeners. See the {api-spring-framework}/test/context/TestExecutionListeners.html[javadoc] @@ -885,7 +865,6 @@ annotation. The following example shows how to use the `@Commit` annotation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -896,7 +875,7 @@ The following example shows how to use the `@Commit` annotation: } ---- <1> Commit the result of the test to the database. -==== + [[spring-testing-annotation-rollback]] ===== `@Rollback` @@ -915,7 +894,6 @@ method, potentially overriding class-level `@Rollback` or `@Commit` semantics. The following example causes a test method's result to not be rolled back (that is, the result is committed to the database): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -926,7 +904,7 @@ result is committed to the database): } ---- <1> Do not roll back the result. -==== + [[spring-testing-annotation-beforetransaction]] ===== `@BeforeTransaction` @@ -939,7 +917,6 @@ transaction by using Spring's `@Transactional` annotation. As of Spring Framewor The following example shows how to use the `@BeforeTransaction` annotation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -949,7 +926,7 @@ The following example shows how to use the `@BeforeTransaction` annotation: } ---- <1> Run this method before a transaction. -==== + [[spring-testing-annotation-aftertransaction]] ===== `@AfterTransaction` @@ -960,7 +937,6 @@ transaction by using Spring's `@Transactional` annotation. As of Spring Framewor `@AfterTransaction` methods are not required to be `public` and may be declared on Java 8-based interface default methods. -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -970,7 +946,7 @@ transaction by using Spring's `@Transactional` annotation. As of Spring Framewor } ---- <1> Run this method after a transaction. -==== + [[spring-testing-annotation-sql]] ===== `@Sql` @@ -979,7 +955,6 @@ transaction by using Spring's `@Transactional` annotation. As of Spring Framewor against a given database during integration tests. The following example shows how to use it: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -990,7 +965,7 @@ it: } ---- <1> Run two scripts for this test. -==== + See <> for further details. @@ -1000,7 +975,6 @@ See <> for further details. `@SqlConfig` defines metadata that is used to determine how to parse and run SQL scripts configured with the `@Sql` annotation. The following example shows how to use it: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1014,7 +988,7 @@ configured with the `@Sql` annotation. The following example shows how to use it } ---- <1> Set the comment prefix and the separator in SQL scripts. -==== + [[spring-testing-annotation-sqlgroup]] ===== `@SqlGroup` @@ -1025,7 +999,6 @@ in conjunction with Java 8's support for repeatable annotations, where `@Sql` ca declared several times on the same class or method, implicitly generating this container annotation. The following example shows how to declare an SQL group: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1039,7 +1012,6 @@ annotation. The following example shows how to declare an SQL group: } ---- <1> Declare a group of SQL scripts. -==== [[integration-testing-annotations-standard]] @@ -1106,7 +1078,6 @@ means the test is implicitly enabled. This is analogous to the semantics of JUni The following example shows a test that has an `@IfProfileValue` annotation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1117,13 +1088,12 @@ The following example shows a test that has an `@IfProfileValue` annotation: } ---- <1> Run this test only when the Java vendor is "Oracle Corporation". -==== + Alternatively, you can configure `@IfProfileValue` with a list of `values` (with `OR` semantics) to achieve TestNG-like support for test groups in a JUnit 4 environment. Consider the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1134,7 +1104,7 @@ Consider the following example: } ---- <1> Run this test for unit tests and integration tests. -==== + [[integration-testing-annotations-junit4-profilevaluesourceconfiguration]] ===== `@ProfileValueSourceConfiguration` @@ -1145,7 +1115,6 @@ of `ProfileValueSource` to use when retrieving profile values configured through test, `SystemProfileValueSource` is used by default. The following example shows how to use `@ProfileValueSourceConfiguration`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1155,7 +1124,7 @@ use `@ProfileValueSourceConfiguration`: } ---- <1> Use a custom profile value source. -==== + [[integration-testing-annotations-junit4-timed]] ===== `@Timed` @@ -1168,7 +1137,6 @@ The time period includes running the test method itself, any repetitions of the `@Repeat`), as well as any setting up or tearing down of the test fixture. The following example shows how to use it: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1178,7 +1146,7 @@ example shows how to use it: } ---- <1> Set the time period for the test to one second. -==== + Spring's `@Timed` annotation has different semantics than JUnit 4's `@Test(timeout=...)` support. Specifically, due to the manner in which JUnit 4 handles test execution timeouts @@ -1197,7 +1165,6 @@ The scope of execution to be repeated includes execution of the test method itse well as any setting up or tearing down of the test fixture. The following example shows how to use the `@Repeat` annotation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1208,7 +1175,7 @@ how to use the `@Repeat` annotation: } ---- <1> Repeat this test ten times. -==== + [[integration-testing-annotations-junit-jupiter]] @@ -1236,7 +1203,6 @@ classes may be declared with the `value` attribute in `@SpringJUnitConfig`. The following example shows how to use the `@SpringJUnitConfig` annotation to specify a configuration class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1246,12 +1212,11 @@ configuration class: } ---- <1> Specify the configuration class. -==== + The following example shows how to use the `@SpringJUnitConfig` annotation to specify the location of a configuration file: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1261,7 +1226,7 @@ location of a configuration file: } ---- <1> Specify the location of a configuration file. -==== + See <> as well as the javadoc for {api-spring-framework}/test/context/junit/jupiter/SpringJUnitConfig.html[`@SpringJUnitConfig`] @@ -1283,7 +1248,6 @@ attribute from `@WebAppConfiguration` only by using the `resourcePath` attribute The following example shows how to use the `@SpringJUnitWebConfig` annotation to specify a configuration class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1293,12 +1257,11 @@ a configuration class: } ---- <1> Specify the configuration class. -==== + The following example shows how to use the `@SpringJUnitWebConfig` annotation to specify a the location of a configuration file: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1308,7 +1271,7 @@ the location of a configuration file: } ---- <1> Specify the location of a configuration file. -==== + See <> as well as the javadoc for {api-spring-framework}/test/context/junit/jupiter/web/SpringJUnitWebConfig.html[`@SpringJUnitWebConfig`], @@ -1341,7 +1304,6 @@ equivalent to `@Disabled` and `@EnabledIf("true")` is logically meaningless. You can use `@EnabledIf` as a meta-annotation to create custom composed annotations. For example, you can create a custom `@EnabledOnMac` annotation as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1353,7 +1315,6 @@ example, you can create a custom `@EnabledOnMac` annotation as follows: ) public @interface EnabledOnMac {} ---- -==== [[integration-testing-annotations-junit-jupiter-disabledif]] ===== `@DisabledIf` @@ -1380,7 +1341,6 @@ equivalent to `@Disabled` and `@DisabledIf("false")` is logically meaningless. You can use `@DisabledIf` as a meta-annotation to create custom composed annotations. For example, you can create a custom `@DisabledOnMac` annotation as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1392,7 +1352,6 @@ example, you can create a custom `@DisabledOnMac` annotation as follows: ) public @interface DisabledOnMac {} ---- -==== [[integration-testing-annotations-meta]] @@ -1432,7 +1391,6 @@ You can use each of the following as a meta-annotation in conjunction with the Consider the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1448,13 +1406,11 @@ Consider the following example: @Transactional public class UserRepositoryTests { } ---- -==== If we discover that we are repeating the preceding configuration across our JUnit 4-based test suite, we can reduce the duplication by introducing a custom composed annotation that centralizes the common test configuration for Spring, as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1465,12 +1421,10 @@ that centralizes the common test configuration for Spring, as follows: @Transactional public @interface TransactionalDevTestConfig { } ---- -==== Then we can use our custom `@TransactionalDevTestConfig` annotation to simplify the configuration of individual JUnit 4 based test classes, as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1482,13 +1436,11 @@ configuration of individual JUnit 4 based test classes, as follows: @TransactionalDevTestConfig public class UserRepositoryTests { } ---- -==== If we write tests that use JUnit Jupiter, we can reduce code duplication even further, since annotations in JUnit 5 can also be used as meta-annotations. Consider the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1504,14 +1456,12 @@ example: @Transactional class UserRepositoryTests { } ---- -==== If we discover that we are repeating the preceding configuration across our JUnit Jupiter-based test suite, we can reduce the duplication by introducing a custom composed annotation that centralizes the common test configuration for Spring and JUnit Jupiter, as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1523,12 +1473,10 @@ as follows: @Transactional public @interface TransactionalDevTestConfig { } ---- -==== Then we can use our custom `@TransactionalDevTestConfig` annotation to simplify the configuration of individual JUnit Jupiter based test classes, as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1538,7 +1486,6 @@ configuration of individual JUnit Jupiter based test classes, as follows: @TransactionalDevTestConfig class UserRepositoryTests { } ---- -==== Since JUnit Jupiter supports the use of `@Test`, `@RepeatedTest`, `ParameterizedTest`, and others as meta-annotations, you can also create custom composed annotations at the @@ -1547,7 +1494,6 @@ the `@Test` and `@Tag` annotations from JUnit Jupiter with the `@Transactional` annotation from Spring, we could create an `@TransactionalIntegrationTest` annotation, as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1558,12 +1504,10 @@ follows: @Test // org.junit.jupiter.api.Test public @interface TransactionalIntegrationTest { } ---- -==== Then we can use our custom `@TransactionalIntegrationTest` annotation to simplify the configuration of individual JUnit Jupiter based test methods, as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1573,7 +1517,6 @@ configuration of individual JUnit Jupiter based test methods, as follows: @TransactionalIntegrationTest void deleteOrder() { } ---- -==== For further details, see the https://github.com/spring-projects/spring-framework/wiki/Spring-Annotation-Programming-Model[Spring Annotation Programming Model] @@ -1786,7 +1729,6 @@ default listeners are not registered. In most common testing scenarios, this eff forces the developer to manually declare all default listeners in addition to any custom listeners. The following listing demonstrates this style of configuration: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1804,7 +1746,6 @@ listeners. The following listing demonstrates this style of configuration: // class body... } ---- -==== The challenge with this approach is that it requires that the developer know exactly which listeners are registered by default. Moreover, the set of default listeners can @@ -1832,7 +1773,6 @@ configures its `order` value (for example, `500`) to be less than the order of t defaults in front of the `ServletTestExecutionListener`, and the previous example could be replaced with the following: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1845,7 +1785,6 @@ be replaced with the following: // class body... } ---- -==== [[testcontext-ctx-management]] @@ -1866,7 +1805,6 @@ As an alternative to implementing the `ApplicationContextAware` interface, you c the application context for your test class through the `@Autowired` annotation on either a field or setter method, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1881,12 +1819,11 @@ a field or setter method, as the following example shows: } ---- <1> Injecting the `ApplicationContext`. -==== + Similarly, if your test is configured to load a `WebApplicationContext`, you can inject the web application context into your test, as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1903,7 +1840,7 @@ the web application context into your test, as follows: ---- <1> Configuring the `WebApplicationContext`. <2> Injecting the `WebApplicationContext`. -==== + Dependency injection by using `@Autowired` is provided by the `DependencyInjectionTestExecutionListener`, which is configured by default (see @@ -1949,7 +1886,6 @@ is treated as an absolute classpath location (for example, `/org/example/config. path that represents a resource URL (i.e., a path prefixed with `classpath:`, `file:`, `http:`, etc.) is used _as is_. -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1962,7 +1898,7 @@ path that represents a resource URL (i.e., a path prefixed with `classpath:`, `f } ---- <1> Setting the locations attribute to a list of XML files. -==== + `@ContextConfiguration` supports an alias for the `locations` attribute through the standard Java `value` attribute. Thus, if you do not need to declare additional @@ -1970,7 +1906,6 @@ attributes in `@ContextConfiguration`, you can omit the declaration of the `loca attribute name and declare the resource locations by using the shorthand format demonstrated in the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1981,7 +1916,7 @@ demonstrated in the following example: } ---- <1> Specifying XML files without using the `location` attribute. -==== + If you omit both the `locations` and the `value` attributes from the `@ContextConfiguration` annotation, the TestContext framework tries to detect a default @@ -1991,7 +1926,6 @@ class. If your class is named `com.example.MyTest`, `GenericXmlContextLoader` lo application context from `"classpath:com/example/MyTest-context.xml"`. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2006,7 +1940,7 @@ example shows how to do so: } ---- <1> Loading configuration from the default location. -==== + [[testcontext-ctx-management-groovy]] ===== Context Configuration with Groovy Scripts @@ -2024,7 +1958,6 @@ TestContext Framework is enabled automatically if Groovy is on the classpath. The following example shows how to specify Groovy configuration files: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2037,7 +1970,7 @@ The following example shows how to specify Groovy configuration files: } ---- <1> Specifying the location of Groovy configuration files. -==== + If you omit both the `locations` and `value` attributes from the `@ContextConfiguration` annotation, the TestContext framework tries to detect a default Groovy script. @@ -2047,7 +1980,6 @@ detect a default location based on the name of the test class. If your class is `"classpath:com/example/MyTestContext.groovy"`. The following example shows how to use the default: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2062,7 +1994,7 @@ the default: } ---- <1> Loading configuration from the default location. -==== + .Declaring XML configuration and Groovy scripts simultaneously [TIP] @@ -2075,7 +2007,6 @@ configured resource location ends with `.xml`, it is loaded by using an The following listing shows how to combine both in an integration test: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2087,7 +2018,6 @@ The following listing shows how to combine both in an integration test: // class body... } ---- -==== ===== [[testcontext-ctx-management-javaconfig]] @@ -2098,7 +2028,6 @@ To load an `ApplicationContext` for your tests by using annotated classes (see class with `@ContextConfiguration` and configure the `classes` attribute with an array that contains references to annotated classes. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2110,7 +2039,7 @@ that contains references to annotated classes. The following example shows how t } ---- <1> Specifying annotated classes. -==== + .Annotated Classes [TIP] @@ -2141,7 +2070,6 @@ example, the `OrderServiceTest` class declares a `static` nested configuration c named `Config` that is automatically used to load the `ApplicationContext` for the test class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2174,7 +2102,7 @@ class: } ---- <1> Loading configuration information from the nested class. -==== + [[testcontext-ctx-management-mixed-config]] ===== Mixing XML, Groovy Scripts, and Annotated Classes @@ -2224,7 +2152,6 @@ order in which the initializers are invoked depends on whether they implement Sp `Ordered` interface or are annotated with Spring's `@Order` annotation or the standard `@Priority` annotation. The following example shows how to use initializers: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2239,7 +2166,7 @@ order in which the initializers are invoked depends on whether they implement Sp } ---- <1> Specifying configuration by using a configuration class and an initializer. -==== + You can also omit the declaration of XML configuration files, Groovy scripts, or annotated classes in `@ContextConfiguration` entirely and instead declare only @@ -2247,7 +2174,6 @@ annotated classes in `@ContextConfiguration` entirely and instead declare only in the context -- for example, by programmatically loading bean definitions from XML files or configuration classes. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2260,7 +2186,7 @@ files or configuration classes. The following example shows how to do so: } ---- <1> Specifying configuration by using only an initializer. -==== + [[testcontext-ctx-management-inheritance]] ===== Context Configuration Inheritance @@ -2287,7 +2213,6 @@ Beans defined in `extended-config.xml` can, therefore, override (that is, replac defined in `base-config.xml`. The following example shows how one class can extend another and use both its own configuration file and the superclass's configuration file: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2308,7 +2233,7 @@ another and use both its own configuration file and the superclass's configurati ---- <1> Configuration file defined in the superclass. <2> Configuration file defined in the subclass. -==== + Similarly, in the next example, which uses annotated classes, the `ApplicationContext` for `ExtendedTest` is loaded from the `BaseConfig` and `ExtendedConfig` classes, in that @@ -2316,7 +2241,6 @@ order. Beans defined in `ExtendedConfig` can, therefore, override (that is, repl those defined in `BaseConfig`. The following example shows how one class can extend another and use both its own configuration class and the superclass's configuration class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2335,7 +2259,7 @@ another and use both its own configuration class and the superclass's configurat ---- <1> Configuration class defined in the superclass. <2> Configuration class defined in the subclass. -==== + In the next example, which uses context initializers, the `ApplicationContext` for `ExtendedTest` is initialized by using `BaseInitializer` and `ExtendedInitializer`. Note, @@ -2344,7 +2268,6 @@ implement Spring's `Ordered` interface or are annotated with Spring's `@Order` a or the standard `@Priority` annotation. The following example shows how one class can extend another and use both its own initializer and the superclass's initializer: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2364,7 +2287,7 @@ extend another and use both its own initializer and the superclass's initializer ---- <1> Initializer defined in the superclass. <2> Initializer defined in the subclass. -==== + [[testcontext-ctx-management-env-profiles]] ===== Context Configuration with Environment Profiles @@ -2382,7 +2305,6 @@ the older `ContextLoader` SPI. Consider two examples with XML configuration and `@Configuration` classes: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2450,7 +2372,6 @@ Consider two examples with XML configuration and `@Configuration` classes: } } ---- -==== When `TransferServiceTest` is run, its `ApplicationContext` is loaded from the `app-config.xml` configuration file in the root of the classpath. If you inspect @@ -2474,7 +2395,6 @@ but define an in-memory data source as a default when neither of these is active The following code listings demonstrate how to implement the same configuration and integration test with `@Configuration` classes instead of XML: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2574,7 +2494,6 @@ integration test with `@Configuration` classes instead of XML: } } ---- -==== In this variation, we have split the XML configuration into four independent `@Configuration` classes: @@ -2600,7 +2519,6 @@ automatically inherit the `@ActiveProfiles` configuration from the base class. I following example, the declaration of `@ActiveProfiles` (as well as other annotations) has been moved to an abstract superclass, `AbstractIntegrationTest`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2634,12 +2552,10 @@ has been moved to an abstract superclass, `AbstractIntegrationTest`: } } ---- -==== `@ActiveProfiles` also supports an `inheritProfiles` attribute that can be used to disable the inheritance of active profiles, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2651,7 +2567,6 @@ disable the inheritance of active profiles, as the following example shows: // test body } ---- -==== [[testcontext-ctx-management-env-profiles-ActiveProfilesResolver]] Furthermore, it is sometimes necessary to resolve active profiles for tests @@ -2670,7 +2585,6 @@ attribute of `@ActiveProfiles`. For further information, see the corresponding The following example demonstrates how to implement and register a custom `OperatingSystemActiveProfilesResolver`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2700,7 +2614,6 @@ The following example demonstrates how to implement and register a custom } } ---- -==== [[testcontext-ctx-management-property-sources]] ===== Context Configuration with Test Property Sources @@ -2744,7 +2657,6 @@ loaded by using the specified resource protocol. Resource location wildcards (su The following example uses a test properties file: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2755,7 +2667,7 @@ The following example uses a test properties file: } ---- <1> Specifying a properties file with an absolute path. -==== + You can configure inlined properties in the form of key-value pairs by using the `properties` attribute of `@TestPropertySource`, as shown in the next example. All @@ -2771,7 +2683,6 @@ a Java properties file: The following example sets two inlined properties: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2782,7 +2693,7 @@ The following example sets two inlined properties: } ---- <1> Setting two properties by using two variations of the key-value syntax. -==== + ====== Default Properties File Detection @@ -2809,7 +2720,6 @@ entries for the `timezone` and `port` properties those are overridden by the inl properties declared by using the `properties` attribute. The following example shows how to specify properties both in a file and inline: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2822,7 +2732,6 @@ to specify properties both in a file and inline: // class body... } ---- -==== ====== Inheriting and Overriding Test Property Sources @@ -2847,7 +2756,6 @@ for `ExtendedTest` is loaded by using the `base.properties` and `extended.proper files as test property source locations. The following example shows how to define properties in both a subclass and its superclass by using `properties` files: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2863,14 +2771,12 @@ properties in both a subclass and its superclass by using `properties` files: // ... } ---- -==== In the next example, the `ApplicationContext` for `BaseTest` is loaded by using only the inlined `key1` property. In contrast, the `ApplicationContext` for `ExtendedTest` is loaded by using the inlined `key1` and `key2` properties. The following example shows how to define properties in both a subclass and its superclass by using inline properties: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2886,7 +2792,6 @@ to define properties in both a subclass and its superclass by using inline prope // ... } ---- -==== [[testcontext-ctx-management-web]] ===== Loading a `WebApplicationContext` @@ -2921,7 +2826,6 @@ loading a `WebApplicationContext`. The following example shows the TestContext framework's support for convention over configuration: .Conventions -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2938,7 +2842,6 @@ framework's support for convention over configuration: //... } ---- -==== If you annotate a test class with `@WebAppConfiguration` without specifying a resource base path, the resource path effectively defaults to `file:src/main/webapp`. Similarly, @@ -2951,7 +2854,6 @@ The following example shows how to explicitly declare a resource base path with `@WebAppConfiguration` and an XML resource location with `@ContextConfiguration`: .Default resource semantics -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2967,7 +2869,6 @@ The following example shows how to explicitly declare a resource base path with //... } ---- -==== The important thing to note here is the different semantics for paths with these two annotations. By default, `@WebAppConfiguration` resource paths are file system based, @@ -2977,7 +2878,6 @@ The following example shows that we can override the default resource semantics annotations by specifying a Spring resource prefix: .Explicit resource semantics -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2993,7 +2893,6 @@ annotations by specifying a Spring resource prefix: //... } ---- -==== Contrast the comments in this example with the previous example. @@ -3017,7 +2916,6 @@ mocks can be autowired into your test instance. Note that the `WebApplicationCon managed per test method by the `ServletTestExecutionListener`. .Injecting mocks -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3046,7 +2944,6 @@ managed per test method by the `ServletTestExecutionListener`. //... } ---- -==== -- [[testcontext-ctx-management-caching]] @@ -3165,7 +3062,6 @@ one for the root `WebApplicationContext` (loaded by using the `TestAppConfig` that is autowired into the test instance is the one for the child context (that is, the lowest context in the hierarchy). The following listing shows this configuration scenario: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3183,7 +3079,6 @@ lowest context in the hierarchy). The following listing shows this configuration // ... } ---- -==== -- @@ -3202,7 +3097,6 @@ based on the configuration in `AbstractWebTests` is set as the parent context fo the contexts loaded for the concrete subclasses. The following listing shows this configuration scenario: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3217,7 +3111,6 @@ configuration scenario: @ContextHierarchy(@ContextConfiguration("/spring/rest-ws-config.xml") public class RestWebServiceTests extends AbstractWebTests {} ---- -==== -- @@ -3235,7 +3128,6 @@ application context loaded from `/app-config.xml` is set as the parent context f contexts loaded from `/user-config.xml` and `{"/user-config.xml", "/order-config.xml"}`. The following listing shows this configuration scenario: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3251,7 +3143,6 @@ The following listing shows this configuration scenario: ) public class ExtendedTests extends BaseTests {} ---- -==== -- .Class hierarchy with overridden context hierarchy configuration @@ -3263,7 +3154,6 @@ application context for `ExtendedTests` is loaded only from `/test-user-config.x has its parent set to the context loaded from `/app-config.xml`. The following listing shows this configuration scenario: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3282,7 +3172,6 @@ shows this configuration scenario: )) public class ExtendedTests extends BaseTests {} ---- -==== .Dirtying a context within a context hierarchy NOTE: If you use `@DirtiesContext` in a test whose context is configured as part of a @@ -3346,7 +3235,6 @@ properly imported through an `import static` declaration that is not shown in th The first code listing shows a JUnit 4 based implementation of the test class that uses `@Autowired` for field injection: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3366,12 +3254,10 @@ The first code listing shows a JUnit 4 based implementation of the test class th } } ---- -==== Alternatively, you can configure the class to use `@Autowired` for setter injection, as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3395,13 +3281,11 @@ follows: } } ---- -==== The preceding code listings use the same XML context file referenced by the `@ContextConfiguration` annotation (that is, `repository-config.xml`). The following shows this configuration: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3422,7 +3306,6 @@ shows this configuration: ---- -==== [NOTE] ===== @@ -3433,7 +3316,6 @@ such a case, you can override the setter method and use the `@Qualifier` annotat indicate a specific target bean, as follows (but make sure to delegate to the overridden method in the superclass as well): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3447,7 +3329,6 @@ method in the superclass as well): // ... ---- -==== The specified qualifier value indicates the specific `DataSource` bean to inject, narrowing the set of type matches to a specific bean. Its value is matched against @@ -3480,7 +3361,6 @@ configure these request parameters through the mock managed by the TestContext f The following listing shows the configuration for this use case: .Request-scoped bean configuration -==== [source,xml,indent=0] ---- @@ -3497,7 +3377,6 @@ The following listing shows the configuration for this use case: ---- -==== In `RequestScopedBeanTests`, we inject both the `UserService` (that is, the subject under test) and the `MockHttpServletRequest` into our test instance. Within our @@ -3509,7 +3388,6 @@ set parameters). We can then perform assertions against the results based on the inputs for the username and password. The following listing shows how to do so: .Request-scoped bean test -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3531,7 +3409,6 @@ inputs for the username and password. The following listing shows how to do so: } } ---- -==== The following code snippet is similar to the one we saw earlier for a request-scoped bean. However, this time, the `userService` bean has a dependency on a session-scoped @@ -3541,7 +3418,6 @@ need to configure a theme in the mock session managed by the TestContext framewo following example shows how to do so: .Session-scoped bean configuration -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -3558,7 +3434,6 @@ following example shows how to do so: ---- -==== In `SessionScopedBeanTests`, we inject the `UserService` and the `MockHttpSession` into our test instance. Within our `sessionScope()` test method, we set up our test fixture by @@ -3569,7 +3444,6 @@ the user service has access to the session-scoped `userPreferences` for the curr configured theme. The following example shows how to do so: .Session-scoped bean test -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3590,7 +3464,6 @@ configured theme. The following example shows how to do so: } } ---- -==== [[testcontext-tx]] @@ -3660,7 +3533,6 @@ are preconfigured for transactional support at the class level. The following example demonstrates a common scenario for writing an integration test for a Hibernate-based `UserRepository`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3704,7 +3576,6 @@ a Hibernate-based `UserRepository`: } } ---- -==== As explained in <>, there is no need to clean up the database after the `createUser()` method runs, since any changes made to the @@ -3733,7 +3604,6 @@ The following example demonstrates some of the features of `TestTransaction`. Se javadoc for {api-spring-framework}/test/context/transaction/TestTransaction.html[`TestTransaction`] for further details. -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3764,7 +3634,6 @@ for further details. } } ---- -==== [[testcontext-tx-before-and-after-tx]] ===== Running Code Outside of a Transaction @@ -3810,7 +3679,6 @@ Transaction management for `@Sql`>> contains an additional example that uses `@S declarative SQL script execution with default transaction rollback semantics. The following example shows the relevant annotations in bold: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3849,10 +3717,10 @@ following example shows the relevant annotations in bold: } ---- -==== [[testcontext-tx-false-positives]] .Avoid false positives when testing ORM code + [NOTE] ===== When you test application code that manipulates the state of a Hibernate session or JPA @@ -3864,7 +3732,6 @@ of work. In the following Hibernate-based example test case, one method demonstr false positive, and the other method correctly exposes the results of flushing the session: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3891,11 +3758,9 @@ session: // ... ---- -==== The following example shows matching methods for JPA: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3922,7 +3787,6 @@ The following example shows matching methods for JPA: // ... ---- -==== ===== @@ -3974,7 +3838,6 @@ to execute the populator against a `javax.sql.DataSource`. The following example specifies SQL scripts for a test schema and test data, sets the statement separator to `@@`, and executes the scripts against a `DataSource`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3989,7 +3852,6 @@ specifies SQL scripts for a test schema and test data, sets the statement separa // execute code that uses the test schema and data } ---- -==== Note that `ResourceDatabasePopulator` internally delegates to `ScriptUtils` for parsing and running SQL scripts. Similarly, the `executeSqlScript(..)` methods in @@ -4021,7 +3883,6 @@ the specified resource protocol. The following example shows how to use `@Sql` at the class level and at the method level within a JUnit Jupiter based integration test class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4041,7 +3902,6 @@ within a JUnit Jupiter based integration test class: } } ---- -==== ====== Default Script Detection @@ -4066,7 +3926,6 @@ Java 8, you can use `@Sql` as a repeatable annotation. Otherwise, you can use th The following example shows how to use `@Sql` as a repeatable annotation with Java 8: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4077,7 +3936,6 @@ The following example shows how to use `@Sql` as a repeatable annotation with Ja // execute code that uses the test schema and test data } ---- -==== In the scenario presented in the preceding example, the `test-schema.sql` script uses a different syntax for single-line comments. @@ -4086,7 +3944,6 @@ The following example is identical to the preceding example, except that the `@S declarations are grouped together within `@SqlGroup`, for compatibility with Java 6 and Java 7. -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4099,7 +3956,6 @@ Java 7. // execute code that uses the test schema and test data } ---- -==== ====== Script Execution Phases @@ -4108,7 +3964,6 @@ you need to run a particular set of scripts after the test method (for example, up database state), you can use the `executionPhase` attribute in `@Sql`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4127,7 +3982,6 @@ following example shows: // to the database outside of the test's transaction } ---- -==== Note that `ISOLATED` and `AFTER_TEST_METHOD` are statically imported from `Sql.TransactionMode` and `Sql.ExecutionPhase`, respectively. @@ -4184,7 +4038,6 @@ reference manual, the javadoc for provide detailed information, and the following example shows a typical testing scenario that uses JUnit Jupiter and transactional tests with `@Sql`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4217,7 +4070,6 @@ that uses JUnit Jupiter and transactional tests with `@Sql`: } } ---- -==== Note that there is no need to clean up the database after the `usersTest()` method is run, since any changes made to the database (either within the test method or within the @@ -4295,7 +4147,6 @@ alternative runner (such as JUnit 4's `Parameterized` runner) or third-party run The following code listing shows the minimal requirements for configuring a test class to run with the custom Spring `Runner`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4309,7 +4160,6 @@ run with the custom Spring `Runner`: } } ---- -==== In the preceding example, `@TestExecutionListeners` is configured with an empty list, to disable the default listeners, which otherwise would require an `ApplicationContext` to @@ -4337,7 +4187,6 @@ To support the full functionality of the TestContext framework, you must combine `SpringClassRule` with a `SpringMethodRule`. The following example shows the proper way to declare these rules in an integration test: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4357,7 +4206,6 @@ to declare these rules in an integration test: } } ---- -==== [[testcontext-support-classes-junit4]] ===== JUnit 4 Support Classes @@ -4422,7 +4270,6 @@ TestNG: The following code listing shows how to configure a test class to use the `SpringExtension` in conjunction with `@ContextConfiguration`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4438,7 +4285,6 @@ The following code listing shows how to configure a test class to use the } } ---- -==== Since you can also use annotations in JUnit 5 as meta-annotations, Spring provides the `@SpringJUnitConfig` and `@SpringJUnitWebConfig` composed annotations to simplify the @@ -4447,7 +4293,6 @@ configuration of the test `ApplicationContext` and JUnit Jupiter. The following example uses `@SpringJUnitConfig` to reduce the amount of configuration used in the previous example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4462,12 +4307,10 @@ used in the previous example: } } ---- -==== Similarly, the following example uses `@SpringJUnitWebConfig` to create a `WebApplicationContext` for use with JUnit Jupiter: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4482,7 +4325,6 @@ Similarly, the following example uses `@SpringJUnitWebConfig` to create a } } ---- -==== See the documentation for `@SpringJUnitConfig` and `@SpringJUnitWebConfig` in <> for further details. @@ -4538,7 +4380,6 @@ In the following example, Spring injects the `OrderService` bean from the `ApplicationContext` loaded from `TestConfig.class` into the `OrderServiceIntegrationTests` constructor. -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4555,7 +4396,6 @@ In the following example, Spring injects the `OrderService` bean from the // tests that use the injected OrderService } ---- -==== Note that this feature lets test dependencies be `final` and therefore immutable. @@ -4570,7 +4410,6 @@ parameter with the corresponding bean from the test's `ApplicationContext`. In the following example, Spring injects the `OrderService` from the `ApplicationContext` loaded from `TestConfig.class` into the `deleteOrder()` test method: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4583,7 +4422,6 @@ loaded from `TestConfig.class` into the `deleteOrder()` test method: } } ---- -==== Due to the robustness of the `ParameterResolver` support in JUnit Jupiter, you can also have multiple dependencies injected into a single method, not only from Spring but also @@ -4592,7 +4430,6 @@ from JUnit Jupiter itself or other third-party extensions. The following example shows how to have both Spring and JUnit Jupiter inject dependencies into the `placeOrderRepeatedly()` test method simultaneously. -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4608,7 +4445,6 @@ into the `placeOrderRepeatedly()` test method simultaneously. } } ---- -==== Note that the use of `@RepeatedTest` from JUnit Jupiter lets the test method gain access to the `RepetitionInfo`. @@ -4696,7 +4532,6 @@ most part, everything should work as it does at runtime with a few notable excep explained in <>. The following JUnit Jupiter-based example uses Spring MVC Test: -==== [source,java,indent=0] ---- import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; @@ -4722,7 +4557,6 @@ Jupiter-based example uses Spring MVC Test: } } ---- -==== The preceding test relies on the `WebApplicationContext` support of the TestContext framework to load Spring configuration from an XML configuration file located in the same @@ -4758,7 +4592,6 @@ Spring MVC configuration through the TestContext framework, which loads the Spri configuration and injects a `WebApplicationContext` into the test to use to build a `MockMvc` instance. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4781,14 +4614,12 @@ configuration and injects a `WebApplicationContext` into the test to use to buil } ---- -==== Your second option is to manually create a controller instance without loading Spring configuration. Instead, basic default configuration, roughly comparable to that of the MVC JavaConfig or the MVC namespace, is automatically created. You can customize it to a degree. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4805,7 +4636,6 @@ degree. The following example shows how to do so: } ---- -==== Which setup option should you use? @@ -4816,7 +4646,6 @@ test suite. Furthermore, you can inject mock services into controllers through S configuration to remain focused on testing the web layer. The following example declares a mock service with Mockito: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4824,12 +4653,10 @@ a mock service with Mockito: ---- -==== You can then inject the mock service into the test to set up and verify your expectations, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4850,7 +4677,6 @@ expectations, as the following example shows: } ---- -==== The `standaloneSetup`, on the other hand, is a little closer to a unit test. It tests one controller at a time. You can manually inject the controller with mock dependencies, and @@ -4873,7 +4699,6 @@ some common and very useful features. For example, you can declare an `Accept` h all requests and expect a status of 200 as well as a `Content-Type` header in all responses, as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4885,14 +4710,12 @@ MockMvc mockMvc = standaloneSetup(new MusicController()) .alwaysExpect(content().contentType("application/json;charset=UTF-8")) .build(); ---- -==== In addition, third-party frameworks (and applications) can pre-package setup instructions, such as those in a `MockMvcConfigurer`. The Spring Framework has one such built-in implementation that helps to save and re-use the HTTP session across requests. You can use it as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4904,7 +4727,6 @@ You can use it as follows: // Use mockMvc to perform requests... ---- -==== See the javadoc for {api-spring-framework}/test/web/servlet/setup/ConfigurableMockMvcBuilder.html[`ConfigurableMockMvcBuilder`] @@ -4915,46 +4737,38 @@ for a list of all MockMvc builder features or use the IDE to explore the availab You can perform requests that use any HTTP method, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- mockMvc.perform(post("/hotels/{id}", 42).accept(MediaType.APPLICATION_JSON)); ---- -==== You can also perform file upload requests that internally use `MockMultipartHttpServletRequest` so that there is no actual parsing of a multipart request. Rather, you have to set it up to be similar to the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- mockMvc.perform(multipart("/doc").file("a1", "ABC".getBytes("UTF-8"))); ---- -==== You can specify query parameters in URI template style, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- mockMvc.perform(get("/hotels?thing={thing}", "somewhere")); ---- -==== You can also add Servlet request parameters that represent either query or form parameters, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- mockMvc.perform(get("/hotels").param("thing", "somewhere")); ---- -==== If application code relies on Servlet request parameters and does not check the query string explicitly (as is most often the case), it does not matter which option you use. @@ -4967,19 +4781,16 @@ request URI. If you must test with the full request URI, be sure to set the `con and `servletPath` accordingly so that request mappings work, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- mockMvc.perform(get("/app/main/hotels/{id}").contextPath("/app").servletPath("/main")) ---- -==== In the preceding example, it would be cumbersome to set the `contextPath` and `servletPath` with every performed request. Instead, you can set up default request properties, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4995,7 +4806,6 @@ properties, as the following example shows: .accept(MediaType.APPLICATION_JSON)).build(); } ---- -==== The preceding properties affect every request performed through the `MockMvc` instance. If the same property is also specified on a given request, it overrides the default @@ -5008,13 +4818,11 @@ they must be specified on every request. You can define expectations by appending one or more `.andExpect(..)` calls after performing a request, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- mockMvc.perform(get("/accounts/1")).andExpect(status().isOk()); ---- -==== `MockMvcResultMatchers.*` provides a number of expectations, some of which are further nested with more detailed expectations. @@ -5031,7 +4839,6 @@ inspect Servlet specific aspects, such as request and session attributes. The following test asserts that binding or validation failed: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5039,13 +4846,11 @@ The following test asserts that binding or validation failed: .andExpect(status().isOk()) .andExpect(model().attributeHasErrors("person")); ---- -==== Many times, when writing tests, it is useful to dump the results of the performed request. You can do so as follows, where `print()` is a static import from `MockMvcResultHandlers`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5054,7 +4859,6 @@ request. You can do so as follows, where `print()` is a static import from .andExpect(status().isOk()) .andExpect(model().attributeHasErrors("person")); ---- -==== As long as request processing does not cause an unhandled exception, the `print()` method prints all the available result data to `System.out`. Spring Framework 4.2 introduced a @@ -5069,19 +4873,16 @@ In some cases, you may want to get direct access to the result and verify someth cannot be verified otherwise. This can be achieved by appending `.andReturn()` after all other expectations, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- MvcResult mvcResult = mockMvc.perform(post("/persons")).andExpect(status().isOk()).andReturn(); // ... ---- -==== If all tests repeat the same expectations, you can set up common expectations once when building the `MockMvc` instance, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5090,7 +4891,6 @@ building the `MockMvc` instance, as the following example shows: .alwaysExpect(content().contentType("application/json;charset=UTF-8")) .build() ---- -==== Note that common expectations are always applied and cannot be overridden without creating a separate `MockMvc` instance. @@ -5099,20 +4899,17 @@ When a JSON response content contains hypermedia links created with https://github.com/spring-projects/spring-hateoas[Spring HATEOAS], you can verify the resulting links by using JsonPath expressions, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- mockMvc.perform(get("/people").accept(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.links[?(@.rel == 'self')].href").value("http://localhost:8080/people")); ---- -==== When XML response content contains hypermedia links created with https://github.com/spring-projects/spring-hateoas[Spring HATEOAS], you can verify the resulting links by using XPath expressions: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -5120,7 +4917,6 @@ resulting links by using XPath expressions: mockMvc.perform(get("/handle").accept(MediaType.APPLICATION_XML)) .andExpect(xpath("/person/ns:link[@rel='self']/@href", ns).string("http://localhost:8080/people")); ---- -==== [[spring-mvc-test-server-filters]] ===== Filter Registrations @@ -5128,13 +4924,11 @@ resulting links by using XPath expressions: When setting up a `MockMvc` instance, you can register one or more Servlet `Filter` instances, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- mockMvc = standaloneSetup(new PersonController()).addFilters(new CharacterEncodingFilter()).build(); ---- -==== Registered filters are invoked through the `MockFilterChain` from `spring-test`, and the last filter delegates to the `DispatcherServlet`. @@ -5226,7 +5020,6 @@ supports paging through all messages. How would you go about testing it? With Spring MVC Test, we can easily test if we are able to create a `Message`, as follows: -==== [source,java,indent=0] ---- MockHttpServletRequestBuilder createMessage = post("/messages/") @@ -5237,12 +5030,10 @@ With Spring MVC Test, we can easily test if we are able to create a `Message`, a .andExpect(status().is3xxRedirection()) .andExpect(redirectedUrl("/messages/123")); ---- -==== What if we want to test the form view that lets us create the message? For example, assume our form looks like the following snippet: -==== [source,xml,indent=0] ----
@@ -5259,26 +5050,22 @@ assume our form looks like the following snippet:
---- -==== How do we ensure that our form produce the correct request to create a new message? A naive attempt might resemble the following: -==== [source,java,indent=0] ---- mockMvc.perform(get("/messages/form")) .andExpect(xpath("//input[@name='summary']").exists()) .andExpect(xpath("//textarea[@name='text']").exists()); ---- -==== This test has some obvious drawbacks. If we update our controller to use the parameter `message` instead of `text`, our form test continues to pass, even though the HTML form is out of synch with the controller. To resolve this we can combine our two tests, as follows: -==== [[spring-mvc-test-server-htmlunit-mock-mvc-test]] [source,java,indent=0] ---- @@ -5296,7 +5083,6 @@ follows: .andExpect(status().is3xxRedirection()) .andExpect(redirectedUrl("/messages/123")); ---- -==== This would reduce the risk of our test incorrectly passing, but there are still some problems: @@ -5383,7 +5169,6 @@ First, make sure that you have included a test dependency on We can easily create an HtmlUnit `WebClient` that integrates with MockMvc by using the `MockMvcWebClientBuilder`, as follows: -==== [source,java,indent=0] ---- @Autowired @@ -5398,7 +5183,6 @@ We can easily create an HtmlUnit `WebClient` that integrates with MockMvc by usi .build(); } ---- -==== NOTE: This is a simple example of using `MockMvcWebClientBuilder`. For advanced usage, see <>. @@ -5415,12 +5199,10 @@ Now we can use HtmlUnit as we normally would but without the need to deploy our application to a Servlet container. For example, we can request the view to create a message with the following: -==== [source,java,indent=0] ---- HtmlPage createMsgFormPage = webClient.getPage("http://localhost/messages/form"); ---- -==== NOTE: The default context path is `""`. Alternatively, we can specify the context path, as described in <>. @@ -5428,7 +5210,6 @@ as described in <>. Once we have a reference to the `HtmlPage`, we can then fill out the form and submit it to create a message, as the following example shows: -==== [source,java,indent=0] ---- HtmlForm form = createMsgFormPage.getHtmlElementById("messageForm"); @@ -5439,12 +5220,10 @@ to create a message, as the following example shows: HtmlSubmitInput submit = form.getOneHtmlElementByAttribute("input", "type", "submit"); HtmlPage newMessagePage = submit.click(); ---- -==== Finally, we can verify that a new message was created successfully. The following assertions use the http://joel-costigliola.github.io/assertj/[AssertJ] library: -==== [source,java,indent=0] ---- assertThat(newMessagePage.getUrl().toString()).endsWith("/messages/123"); @@ -5455,7 +5234,6 @@ assertions use the http://joel-costigliola.github.io/assertj/[AssertJ] library: String text = newMessagePage.getHtmlElementById("text").getTextContent(); assertThat(text).isEqualTo("In case you didn't know, Spring Rocks!"); ---- -==== The preceding code improves on our <> in a number of ways. @@ -5477,7 +5255,6 @@ In the examples so far, we have used `MockMvcWebClientBuilder` in the simplest w possible, by building a `WebClient` based on the `WebApplicationContext` loaded for us by the Spring TestContext Framework. This approach is repeated in the following example: -==== [source,java,indent=0] ---- @Autowired @@ -5492,11 +5269,9 @@ the Spring TestContext Framework. This approach is repeated in the following exa .build(); } ---- -==== We can also specify additional configuration options, as the following example shows: -==== [source,java,indent=0] ---- WebClient webClient; @@ -5514,12 +5289,10 @@ We can also specify additional configuration options, as the following example s .build(); } ---- -==== As an alternative, we can perform the exact same setup by configuring the `MockMvc` instance separately and supplying it to the `MockMvcWebClientBuilder`, as follows: -==== [source,java,indent=0] ---- MockMvc mockMvc = MockMvcBuilders @@ -5536,7 +5309,6 @@ instance separately and supplying it to the `MockMvcWebClientBuilder`, as follow .useMockMvcForHosts("example.com","example.org") .build(); ---- -==== This is more verbose, but, by building the `WebClient` with a `MockMvc` instance, we have the full power of MockMvc at our fingertips. @@ -5572,19 +5344,16 @@ afterwards. If one of the fields were named "`summary`", we might have something that resembles the following repeated in multiple places within our tests: -==== [source,java,indent=0] ---- HtmlTextInput summaryInput = currentPage.getHtmlElementById("summary"); summaryInput.setValueAttribute(summary); ---- -==== So what happens if we change the `id` to `smmry`? Doing so would force us to update all of our tests to incorporate this change. This violates the DRY principle, so we should ideally extract this code into its own method, as follows: -==== [source,java,indent=0] ---- public HtmlPage createMessage(HtmlPage currentPage, String summary, String text) { @@ -5597,14 +5366,12 @@ ideally extract this code into its own method, as follows: summaryInput.setValueAttribute(summary); } ---- -==== Doing so ensures that we do not have to update all of our tests if we change the UI. We might even take this a step further and place this logic within an `Object` that represents the `HtmlPage` we are currently on, as the following example shows: -==== [source,java,indent=0] ---- public class CreateMessagePage { @@ -5639,7 +5406,6 @@ represents the `HtmlPage` we are currently on, as the following example shows: } } ---- -==== Formerly, this pattern was known as the https://github.com/SeleniumHQ/selenium/wiki/PageObjects[Page Object Pattern]. While we @@ -5655,7 +5421,6 @@ includes a test dependency on `org.seleniumhq.selenium:selenium-htmlunit-driver` We can easily create a Selenium WebDriver that integrates with MockMvc by using the `MockMvcHtmlUnitDriverBuilder` as the following example shows: -==== [source,java,indent=0] ---- @Autowired @@ -5670,7 +5435,6 @@ We can easily create a Selenium WebDriver that integrates with MockMvc by using .build(); } ---- -==== NOTE: This is a simple example of using `MockMvcHtmlUnitDriverBuilder`. For more advanced usage, see <>. @@ -5687,22 +5451,18 @@ Now we can use WebDriver as we normally would but without the need to deploy our application to a Servlet container. For example, we can request the view to create a message with the following: -==== [source,java,indent=0] ---- CreateMessagePage page = CreateMessagePage.to(driver); ---- -==== We can then fill out the form and submit it to create a message, as follows: -==== [source,java,indent=0] ---- ViewMessagePage viewMessagePage = page.createMessage(ViewMessagePage.class, expectedSummary, expectedText); ---- -==== This improves on the design of our <> by leveraging the Page Object Pattern. As we mentioned in @@ -5710,7 +5470,6 @@ test>> by leveraging the Page Object Pattern. As we mentioned in with HtmlUnit, but it is much easier with WebDriver. Consider the following `CreateMessagePage` implementation: -==== [source,java,indent=0] ---- public class CreateMessagePage @@ -5760,23 +5519,20 @@ by the `id` or `name` of the element within the HTML page. https://github.com/SeleniumHQ/selenium/wiki/PageFactory#making-the-example-work-using-annotations[`@FindBy` annotation] to override the default lookup behavior. Our example shows how to use the `@FindBy` annotation to look up our submit button with a `css` selector (*input[type=submit]*). -==== + Finally, we can verify that a new message was created successfully. The following assertions use the http://joel-costigliola.github.io/assertj/[AssertJ] assertion library: -==== [source,java,indent=0] ---- assertThat(viewMessagePage.getMessage()).isEqualTo(expectedMessage); assertThat(viewMessagePage.getSuccess()).isEqualTo("Successfully created a new message"); ---- -==== We can see that our `ViewMessagePage` lets us interact with our custom domain model. For example, it exposes a method that returns a `Message` object: -==== [source,java,indent=0] ---- public Message getMessage() throws ParseException { @@ -5788,14 +5544,12 @@ example, it exposes a method that returns a `Message` object: return message; } ---- -==== We can then use the rich domain objects in our assertions. Lastly, we must not forget to close the `WebDriver` instance when the test is complete, as follows: -==== [source,java,indent=0] ---- @After @@ -5805,7 +5559,6 @@ as follows: } } ---- -==== For additional information on using WebDriver, see the Selenium https://github.com/SeleniumHQ/selenium/wiki/Getting-Started[WebDriver documentation]. @@ -5817,7 +5570,6 @@ In the examples so far, we have used `MockMvcHtmlUnitDriverBuilder` in the simpl possible, by building a `WebDriver` based on the `WebApplicationContext` loaded for us by the Spring TestContext Framework. This approach is repeated here, as follows: -==== [source,java,indent=0] ---- @Autowired @@ -5832,11 +5584,9 @@ the Spring TestContext Framework. This approach is repeated here, as follows: .build(); } ---- -==== We can also specify additional configuration options, as follows: -==== [source,java,indent=0] ---- WebDriver driver; @@ -5854,12 +5604,10 @@ We can also specify additional configuration options, as follows: .build(); } ---- -==== As an alternative, we can perform the exact same setup by configuring the `MockMvc` instance separately and supplying it to the `MockMvcHtmlUnitDriverBuilder`, as follows: -==== [source,java,indent=0] ---- MockMvc mockMvc = MockMvcBuilders @@ -5876,7 +5624,6 @@ instance separately and supplying it to the `MockMvcHtmlUnitDriverBuilder`, as f .useMockMvcForHosts("example.com","example.org") .build(); ---- -==== This is more verbose, but, by building the `WebDriver` with a `MockMvc` instance, we have the full power of MockMvc at our fingertips. @@ -5904,7 +5651,6 @@ boilerplate code for us. We can easily initialize a Geb `Browser` with a Selenium WebDriver that uses MockMvc, as follows: -==== [source,groovy] ---- def setup() { @@ -5913,7 +5659,6 @@ def setup() { .build() } ---- -==== NOTE: This is a simple example of using `MockMvcHtmlUnitDriverBuilder`. For more advanced usage, see <>. @@ -5930,16 +5675,13 @@ Now we can use Geb as we normally would but without the need to deploy our appli a Servlet container. For example, we can request the view to create a message with the following: -==== [source,groovy] ---- to CreateMessagePage ---- -==== We can then fill out the form and submit it to create a message, as follows: -==== [source,groovy] ---- when: @@ -5947,7 +5689,6 @@ form.summary = expectedSummary form.text = expectedMessage submit.click(ViewMessagePage) ---- -==== Any unrecognized method calls or property accesses or references that are not found are forwarded to the current page object. This removes a lot of the boilerplate code we @@ -5959,7 +5700,6 @@ Pattern. As mentioned previously, we can use the Page Object Pattern with HtmlUn WebDriver, but it is even easier with Geb. Consider our new Groovy-based `CreateMessagePage` implementation: -==== [source,groovy] ---- class CreateMessagePage extends Page { @@ -5972,31 +5712,26 @@ class CreateMessagePage extends Page { } } ---- -==== Our `CreateMessagePage` extends `Page`. We do not go over the details of `Page`, but, in summary, it contains common functionality for all of our pages. We define a URL in which this page can be found. This lets us navigate to the page, as follows: -==== [source,groovy] ---- to CreateMessagePage ---- -==== We also have an `at` closure that determines if we are at the specified page. It should return `true` if we are on the correct page. This is why we can assert that we are on the correct page, as follows: -==== [source,groovy] ---- then: at CreateMessagePage errors.contains('This field is required.') ---- -==== NOTE: We use an assertion in the closure so that we can determine where things went wrong if we were at the wrong page. @@ -6008,7 +5743,6 @@ API] to select the content in which we are interested. Finally, we can verify that a new message was created successfully, as follows: -==== [source,groovy] ---- then: @@ -6019,7 +5753,6 @@ date summary == expectedSummary message == expectedMessage ---- -==== For further details on how to get the most out of Geb, see http://www.gebish.org/manual/current/[The Book of Geb] user's manual. @@ -6033,7 +5766,6 @@ idea is to declare expected requests and to provide "`stub`" responses so that y focus on testing the code in isolation (that is, without running a server). The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6046,7 +5778,6 @@ example shows how to do so: mockServer.verify(); ---- -==== In the preceding example, `MockRestServiceServer` (the central class for client-side REST tests) configures the `RestTemplate` with a custom `ClientHttpRequestFactory` that @@ -6062,20 +5793,17 @@ can set the `ignoreExpectOrder` option when building the server, in which case a expectations are checked (in order) to find a match for a given request. That means requests are allowed to come in any order. The following example uses `ignoreExpectOrder`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- server = MockRestServiceServer.bindTo(restTemplate).ignoreExpectOrder(true).build(); ---- -==== Even with unordered requests by default, each request is allowed to execute once only. The `expect` method provides an overloaded variant that accepts an `ExpectedCount` argument that specifies a count range (for example, `once`, `manyTimes`, `max`, `min`, `between`, and so on). The following example uses `times`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6089,7 +5817,6 @@ argument that specifies a count range (for example, `once`, `manyTimes`, `max`, mockServer.verify(); ---- -==== Note that, when `ignoreExpectOrder` is not set (the default), and, therefore, requests are expected in order of declaration, then that order applies only to the first of any @@ -6103,7 +5830,6 @@ As an alternative to all of the above, the client-side test support also provide bind it to a `MockMvc` instance. That allows processing requests using actual server-side logic but without running a server. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6112,7 +5838,6 @@ logic but without running a server. The following example shows how to do so: // Test code that uses the above RestTemplate ... ---- -==== [[spring-mvc-test-client-static-imports]] ===== Static Imports @@ -6144,7 +5869,6 @@ https://github.com/spring-projects/spring-petclinic[GitHub], shows several featu the Spring TestContext Framework in a JUnit 4 environment. Most test functionality is included in the `AbstractClinicTests`, for which a partial listing follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6185,7 +5909,7 @@ method to easily verify the number of rows in a given table, thus verifying corr behavior of the application code being tested. This allows for stronger tests and lessens dependency on the exact test data. For example, you can add additional rows in the database without breaking tests. -==== + Like many integration tests that use a database, most of the tests in `AbstractClinicTests` depend on a minimum amount of data already being in the database @@ -6210,7 +5934,6 @@ inherited locations) and `HibernateClinicTests-context.xml`, with `AbstractClinicTests-context.xml`. The following listing shows the definition of the `HibernateClinicTests` class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -6218,7 +5941,7 @@ inherited locations) and `HibernateClinicTests-context.xml`, with public class HibernateClinicTests extends AbstractClinicTests { } ---- <1> Load the application context from `AbstractClinicTests-context.xml` and `HibernateClinicTests-context.xml`. -==== + In a large-scale application, the Spring configuration is often split across multiple files. Consequently, configuration locations are typically specified in a common base diff --git a/src/docs/asciidoc/web/integration.adoc b/src/docs/asciidoc/web/integration.adoc index 0d130d8edf..d0bd218380 100644 --- a/src/docs/asciidoc/web/integration.adoc +++ b/src/docs/asciidoc/web/integration.adoc @@ -43,7 +43,6 @@ set of Spring XML configuration files to load. Consider the following `` configuration: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -51,11 +50,9 @@ Consider the following `` configuration: org.springframework.web.context.ContextLoaderListener ---- -==== Further consider the following `` configuration: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -64,7 +61,6 @@ Further consider the following `` configuration: /WEB-INF/applicationContext*.xml ---- -==== If you do not specify the `contextConfigLocation` context parameter, the `ContextLoaderListener` looks for a file called `/WEB-INF/applicationContext.xml` to @@ -79,13 +75,11 @@ created by the `ContextLoaderListener`. The following example shows how to get the `WebApplicationContext`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext); ---- -==== The {api-spring-framework}/web/context/support/WebApplicationContextUtils.html[`WebApplicationContextUtils`] @@ -140,7 +134,6 @@ implementation. Configuration-wise, you can define `SpringBeanFacesELResolver` in your JSF `faces-context.xml` file, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -151,7 +144,6 @@ Configuration-wise, you can define `SpringBeanFacesELResolver` in your JSF ---- -==== @@ -166,13 +158,11 @@ takes a `FacesContext` parameter rather than a `ServletContext` parameter. The following example shows how to use `FacesContextUtils`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- ApplicationContext ctx = FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance()); ---- -==== diff --git a/src/docs/asciidoc/web/web-uris.adoc b/src/docs/asciidoc/web/web-uris.adoc index 7c1453a58f..c96118cad2 100644 --- a/src/docs/asciidoc/web/web-uris.adoc +++ b/src/docs/asciidoc/web/web-uris.adoc @@ -4,7 +4,6 @@ `UriComponentsBuilder` helps to build URI's from URI templates with variables, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -21,12 +20,11 @@ <3> Request to have the URI template and URI variables encoded. <4> Build a `UriComponents`. <5> Expand variables and obtain the `URI`. -==== + The preceding example can be consolidated into one chain and shortened with `buildAndExpand`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -37,12 +35,10 @@ as the following example shows: .buildAndExpand("Westin", "123") .toUri(); ---- -==== You can shorten it further by going directly to a URI (which implies encoding), as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -51,11 +47,9 @@ as the following example shows: .queryParam("q", "{q}") .build("Westin", "123"); ---- -==== You shorter it further still with a full URI template, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -63,7 +57,6 @@ You shorter it further still with a full URI template, as the following example .fromUriString("http://example.com/hotels/{hotel}?q={q}") .build("Westin", "123"); ---- -==== @@ -83,7 +76,6 @@ exposes shared configuration options. The following example shows how to configure a `RestTemplate`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -96,11 +88,9 @@ The following example shows how to configure a `RestTemplate`: RestTemplate restTemplate = new RestTemplate(); restTemplate.setUriTemplateHandler(factory); ---- -==== The following example configures a `WebClient`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -112,13 +102,11 @@ The following example configures a `WebClient`: WebClient client = WebClient.builder().uriBuilderFactory(factory).build(); ---- -==== In addition, you can also use `DefaultUriBuilderFactory` directly. It is similar to using `UriComponentsBuilder` but, instead of static factory methods, it is an actual instance that holds configuration and preferences, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -129,7 +117,6 @@ that holds configuration and preferences, as the following example shows: .queryParam("q", "{q}") .build("Westin", "123"); ---- -==== @@ -157,7 +144,6 @@ URI variables intentionally contain reserved characters. The following example uses the first option: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -169,12 +155,10 @@ URI uri = UriComponentsBuilder.fromPath("/hotel list/{city}") // Result is "/hotel%20list/New%20York?q=foo%2Bbar" ---- -==== You can shorten the preceding example by going directly to the URI (which implies encoding), as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -182,24 +166,20 @@ URI uri = UriComponentsBuilder.fromPath("/hotel list/{city}") .queryParam("q", "{q}") .build("New York", "foo+bar") ---- -==== You can shorten it further still with a full URI template, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- URI uri = UriComponentsBuilder.fromPath("/hotel list/{city}?q={q}") .build("New York", "foo+bar") ---- -==== The `WebClient` and the `RestTemplate` expand and encode URI templates internally through the `UriBuilderFactory` strategy. Both can be configured with a custom strategy. as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -214,7 +194,6 @@ as the following example shows: // Customize the WebClient.. WebClient client = WebClient.builder().uriBuilderFactory(factory).build(); ---- -==== The `DefaultUriBuilderFactory` implementation uses `UriComponentsBuilder` internally to expand and encode URI templates. As a factory, it provides a single place to configure diff --git a/src/docs/asciidoc/web/webflux-cors.adoc b/src/docs/asciidoc/web/webflux-cors.adoc index 66d6e738d4..baa9aee162 100644 --- a/src/docs/asciidoc/web/webflux-cors.adoc +++ b/src/docs/asciidoc/web/webflux-cors.adoc @@ -83,7 +83,6 @@ The {api-spring-framework}/web/bind/annotation/CrossOrigin.html[`@CrossOrigin`] annotation enables cross-origin requests on annotated controller methods, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -103,7 +102,6 @@ public class AccountController { } } ---- -==== By default, `@CrossOrigin` allows: @@ -121,7 +119,6 @@ should be used only where appropriate. `@CrossOrigin` is supported at the class level, too, and inherited by all methods. The following example specifies a certain domain and sets `maxAge` to an hour: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -141,11 +138,9 @@ public class AccountController { } } ---- -==== You can use `@CrossOrigin` at both the class and the method level, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] @@ -169,8 +164,6 @@ public class AccountController { ---- <1> Using `@CrossOrigin` at the class level. <2> Using `@CrossOrigin` at the method level. -==== - @@ -198,7 +191,6 @@ should be used only where appropriate. To enable CORS in the WebFlux Java configuration, you can use the `CorsRegistry` callback, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -220,7 +212,6 @@ public class WebConfig implements WebFluxConfigurer { } } ---- -==== @@ -236,7 +227,6 @@ good fit with <>. To configure the filter, you can declare a `CorsWebFilter` bean and pass a `CorsConfigurationSource` to its constructor, as the following example shows: -==== [source,java,indent=0] [subs="verbatim"] ---- @@ -259,4 +249,3 @@ CorsWebFilter corsFilter() { return new CorsWebFilter(source); } ---- -==== diff --git a/src/docs/asciidoc/web/webflux-functional.adoc b/src/docs/asciidoc/web/webflux-functional.adoc index a99319ca8e..a7f26e3955 100644 --- a/src/docs/asciidoc/web/webflux-functional.adoc +++ b/src/docs/asciidoc/web/webflux-functional.adoc @@ -28,7 +28,6 @@ difference that router functions provide not just data, but also behavior. `RouterFunctions.route()` provides a router builder that facilitates the creation of routers, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -63,7 +62,6 @@ public class PersonHandler { } } ---- -==== One way to run a `RouterFunction` is to turn it into an `HttpHandler` and install it through one of the built-in <>: @@ -97,62 +95,50 @@ while access to the body is provided through the `body` methods. The following example extracts the request body to a `Mono`: -==== [source,java] ---- Mono string = request.bodyToMono(String.class); ---- -==== The following example extracts the body to a `Flux`, where `Person` objects are decoded from some serialized form, such as JSON or XML: -==== [source,java] ---- Flux people = request.bodyToFlux(Person.class); ---- -==== The preceding examples are shortcuts that use the more general `ServerRequest.body(BodyExtractor)`, which accepts the `BodyExtractor` functional strategy interface. The utility class `BodyExtractors` provides access to a number of instances. For example, the preceding examples can also be written as follows: -==== [source,java] ---- Mono string = request.body(BodyExtractors.toMono(String.class)); Flux people = request.body(BodyExtractors.toFlux(Person.class)); ---- -==== The following example shows how to access form data: -==== [source,java] ---- Mono map = request.body(BodyExtractors.toFormData()); ---- -==== The following example shows how to access multipart data as a map: -==== [source,java] ---- Mono map = request.body(BodyExtractors.toMultipartData()); ---- -==== The following example shows how to access multiparts, one at a time, in streaming fashion: -==== [source,java] ---- Flux parts = request.body(BodyExtractos.toParts()); ---- -==== @@ -164,23 +150,19 @@ a `build` method to create it. You can use the builder to set the response statu headers, or to provide a body. The following example creates a 200 (OK) response with JSON content: -==== [source,java] ---- Mono person = ... ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(person, Person.class); ---- -==== The following example shows how to build a 201 (CREATED) response with a `Location` header and no body: -==== [source,java] ---- URI location = ... ServerResponse.created(location).build(); ---- -==== @@ -189,14 +171,12 @@ ServerResponse.created(location).build(); We can write a handler function as a lambda, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- HandlerFunction helloWorld = request -> ServerResponse.ok().body(fromObject("Hello World")); ---- -==== That is convenient, but in an application we need multiple functions, and multiple inline lambda's can get messy. @@ -204,7 +184,6 @@ Therefore, it is useful to group related handler functions together into a handl has a similar role as `@Controller` in an annotation-based application. For example, the following class exposes a reactive `Person` repository: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -248,7 +227,6 @@ when the `Person` has been saved). <3> `getPerson` is a handler function that returns a single person, identified by the `id` path variable. We retrieve that `Person` from the repository and create a JSON response, if it is found. If it is not found, we use `switchIfEmpty(Mono)` to return a 404 Not Found response. -==== @@ -324,7 +302,6 @@ and so on. The following example uses a request predicate to create a constraint based on the `Accept` header: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -332,7 +309,6 @@ RouterFunction route = RouterFunctions.route() .GET("/hello-world", accept(MediaType.TEXT_PLAIN), request -> Response.ok().body(fromObject("Hello World"))); ---- -==== You can compose multiple request predicates together by using: @@ -368,7 +344,6 @@ There are also other ways to compose multiple router functions together: The following example shows the composition of four routes: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -395,7 +370,6 @@ RouterFunction route = route() `PersonHandler.createPerson`, and <4> `otherRoute` is a router function that is created elsewhere, and added to the route built. -==== === Nested Routes @@ -409,7 +383,6 @@ When using annotations, you would remove this duplication by using a type-level In WebFlux.fn, path predicates can be shared through the `path` method on the router function builder. For instance, the last few lines of the example above can be improved in the following way by using nested routes: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -420,7 +393,6 @@ RouterFunction route = route() .POST("/person", handler::createPerson)) .build(); ---- -==== Note that second parameter of `path` is a consumer that takes the a router builder. @@ -429,7 +401,6 @@ the `nest` method on the builder. The above still contains some duplication in the form of the shared `Accept`-header predicate. We can further improve by using the `nest` method together with `accept`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -441,7 +412,6 @@ RouterFunction route = route() .POST("/person", handler::createPerson)) .build(); ---- -==== [[webflux-fn-running]] @@ -478,7 +448,6 @@ starter. The following example shows a WebFlux Java configuration (see <> for how to run it): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -514,7 +483,6 @@ public class WebConfig implements WebFluxConfigurer { } } ---- -==== @@ -529,7 +497,6 @@ The filter will apply to all routes that are built by the builder. This means that filters defined in nested routes do not apply to "top-level" routes. For instance, consider the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -547,7 +514,7 @@ RouterFunction route = route() ---- <1> The `before` filter that adds a custom request header is only applied to the two GET routes. <2> The `after` filter that logs the response is applied to all routes, including the nested ones. -==== + The `filter` method on the router builder takes a `HandlerFilterFunction`: a function that takes a `ServerRequest` and `HandlerFunction` and returns a `ServerResponse`. @@ -559,7 +526,6 @@ Now we can add a simple security filter to our route, assuming that we have a `S can determine whether a particular path is allowed. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -582,7 +548,6 @@ RouterFunction route = route() }) .build(); ---- -==== The preceding example demonstrates that invoking the `next.handle(ServerRequest)` is optional. We allow only the handler function to be executed when access is allowed. diff --git a/src/docs/asciidoc/web/webflux-view.adoc b/src/docs/asciidoc/web/webflux-view.adoc index 2377ba15a7..1107ae370d 100644 --- a/src/docs/asciidoc/web/webflux-view.adoc +++ b/src/docs/asciidoc/web/webflux-view.adoc @@ -47,7 +47,6 @@ integration for using Spring WebFlux with FreeMarker templates. The following example shows how to configure FreeMarker as a view technology: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -70,7 +69,6 @@ The following example shows how to configure FreeMarker as a view technology: } } ---- -==== Your templates need to be stored in the directory specified by the `FreeMarkerConfigurer`, shown in the preceding example. Given the preceding configuration, if your controller returns the view name, @@ -89,7 +87,6 @@ the `FreeMarkerConfigurer` bean. The `freemarkerSettings` property requires a `java.util.Properties` object, and the `freemarkerVariables` property requires a `java.util.Map`. The following example shows how to use a `FreeMarkerConfigurer`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -111,7 +108,6 @@ the `FreeMarkerConfigurer` bean. The `freemarkerSettings` property requires a } } ---- -==== See the FreeMarker documentation for details of settings and variables as they apply to the `Configuration` object. @@ -173,7 +169,6 @@ You can declare a `ScriptTemplateConfigurer` bean to specify the script engine t the script files to load, what function to call to render templates, and so on. The following example uses Mustache templates and the Nashorn JavaScript engine: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -197,7 +192,6 @@ The following example uses Mustache templates and the Nashorn JavaScript engine: } } ---- -==== The `render` function is called with the following parameters: @@ -217,7 +211,6 @@ http://en.wikipedia.org/wiki/Polyfill[polyfill] in order to emulate some browser facilities not available in the server-side script engine. The following example shows how to set a custom render function: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -241,7 +234,6 @@ The following example shows how to set a custom render function: } } ---- -==== NOTE: Setting the `sharedEngine` property to `false` is required when using non-thread-safe script engines with templating libraries not designed for concurrency, such as Handlebars or @@ -251,13 +243,11 @@ to https://bugs.openjdk.java.net/browse/JDK-8076099[this bug]. `polyfill.js` defines only the `window` object needed by Handlebars to run properly, as the following snippet shows: -==== [source,javascript,indent=0] [subs="verbatim,quotes"] ---- var window = {}; ---- -==== This basic `render.js` implementation compiles the template before using it. A production ready implementation should also store and reused cached templates or pre-compiled templates. @@ -265,7 +255,6 @@ This can be done on the script side, as well as any customization you need (mana template engine configuration for example). The following example shows how compile a template: -==== [source,javascript,indent=0] [subs="verbatim,quotes"] ---- @@ -274,7 +263,6 @@ The following example shows how compile a template: return compiledTemplate(model); } ---- -==== Check out the Spring Framework unit tests, https://github.com/spring-projects/spring-framework/tree/master/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/script[Java], and diff --git a/src/docs/asciidoc/web/webflux-webclient.adoc b/src/docs/asciidoc/web/webflux-webclient.adoc index f6f9b76a1e..0ada590ff6 100644 --- a/src/docs/asciidoc/web/webflux-webclient.adoc +++ b/src/docs/asciidoc/web/webflux-webclient.adoc @@ -38,7 +38,6 @@ You can also use `WebClient.builder()` with further options: The following example configures <>: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -52,12 +51,10 @@ The following example configures < .exchangeStrategies(strategies) .build(); ---- -==== Once built, a `WebClient` instance is immutable. However, you can clone it and build a modified copy without affecting the original instance, as the following example shows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -71,7 +68,6 @@ modified copy without affecting the original instance, as the following example // client2 has filterA, filterB, filterC, filterD ---- -==== @@ -80,7 +76,6 @@ modified copy without affecting the original instance, as the following example To customize Reactor Netty settings, simple provide a pre-configured `HttpClient`: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -90,7 +85,6 @@ To customize Reactor Netty settings, simple provide a pre-configured `HttpClient .clientConnector(new ReactorClientHttpConnector(httpClient)) .build(); ---- -==== [[webflux-client-builder-reactor-resources]] @@ -108,7 +102,6 @@ application deployed as a WAR), you can declare a Spring-managed bean of type Netty global resources are shut down when the Spring `ApplicationContext` is closed, as the following example shows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -117,13 +110,11 @@ as the following example shows: return new ReactorResourceFactory(); } ---- -==== You can also choose not to participate in the global Reactor Netty resources. However, in this mode, the burden is on you to ensure that all Reactor Netty client and server instances use shared resources, as the following example shows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -150,7 +141,6 @@ instances use shared resources, as the following example shows: <1> Create resources independent of global ones. <2> Use the `ReactorClientHttpConnector` constructor with resource factory. <3> Plug the connector into the `WebClient.Builder`. -==== [[webflux-client-builder-reactor-timeout]] @@ -158,7 +148,6 @@ instances use shared resources, as the following example shows: To configure a connection timeout: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -168,11 +157,9 @@ HttpClient httpClient = HttpClient.create() .tcpConfiguration(client -> client.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)); ---- -==== To configure a read and/or write timeout values: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -185,7 +172,6 @@ HttpClient httpClient = HttpClient.create() .addHandlerLast(new ReadTimeoutHandler(10)) .addHandlerLast(new WriteTimeoutHandler(10)))); ---- -==== @@ -194,7 +180,6 @@ HttpClient httpClient = HttpClient.create() The following example shows how to customize Jetty `HttpClient` settings: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -204,7 +189,6 @@ The following example shows how to customize Jetty `HttpClient` settings: WebClient webClient = WebClient.builder().clientConnector(connector).build(); ---- -==== By default, `HttpClient` creates its own resources (`Executor`, `ByteBufferPool`, `Scheduler`), which remain active until the process exits or `stop()` is called. @@ -214,7 +198,6 @@ ensure that the resources are shut down when the Spring `ApplicationContext` is declaring a Spring-managed bean of type `JettyResourceFactory`, as the following example shows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -238,7 +221,6 @@ shows: ---- <1> Use the `JettyClientHttpConnector` constructor with resource factory. <2> Plug the connector into the `WebClient.Builder`. -==== @@ -249,7 +231,6 @@ shows: The `retrieve()` method is the easiest way to get a response body and decode it. The following example shows how to do so: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -260,11 +241,9 @@ The following example shows how to do so: .retrieve() .bodyToMono(Person.class); ---- -==== You can also get a stream of objects decoded from the response, as the following example shows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -273,7 +252,6 @@ You can also get a stream of objects decoded from the response, as the following .retrieve() .bodyToFlux(Quote.class); ---- -==== By default, responses with 4xx or 5xx status codes result in an `WebClientResponseException` or one of its HTTP status specific sub-classes, such as @@ -281,7 +259,6 @@ By default, responses with 4xx or 5xx status codes result in an You can also use the `onStatus` method to customize the resulting exception, as the following example shows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -292,7 +269,6 @@ as the following example shows: .onStatus(HttpStatus::is5xxServerError, response -> ...) .bodyToMono(Person.class); ---- -==== When `onStatus` is used, if the response is expected to have content, then the `onStatus` callback should consume it. If not, the content will be automatically drained to ensure @@ -307,7 +283,6 @@ resources are released. The `exchange()` method provides more control than the `retrieve` method. The following example is equivalent to `retrieve()` but also provides access to the `ClientResponse`: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -316,11 +291,9 @@ to `retrieve()` but also provides access to the `ClientResponse`: .exchange() .flatMap(response -> response.bodyToMono(Person.class)); ---- -==== At this level, you can also create a full `ResponseEntity`: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -329,7 +302,6 @@ At this level, you can also create a full `ResponseEntity`: .exchange() .flatMap(response -> response.toEntity(Person.class)); ---- -==== Note that (unlike `retrieve()`), with `exchange()`, there are no automatic error signals for 4xx and 5xx responses. You have to check the status code and decide how to proceed. @@ -348,7 +320,6 @@ is closed and is not placed back in the pool. The request body can be encoded from an `Object`, as the following example shows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -361,11 +332,9 @@ The request body can be encoded from an `Object`, as the following example shows .retrieve() .bodyToMono(Void.class); ---- -==== You can also have a stream of objects be encoded, as the following example shows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -378,12 +347,10 @@ You can also have a stream of objects be encoded, as the following example shows .retrieve() .bodyToMono(Void.class); ---- -==== Alternatively, if you have the actual value, you can use the `syncBody` shortcut method, as the following example shows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -396,7 +363,6 @@ as the following example shows: .retrieve() .bodyToMono(Void.class); ---- -==== @@ -407,7 +373,6 @@ To send form data, you can provide a `MultiValueMap` as the body content is automatically set to `application/x-www-form-urlencoded` by the `FormHttpMessageWriter`. The following example shows how to use `MultiValueMap`: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -419,11 +384,9 @@ content is automatically set to `application/x-www-form-urlencoded` by the .retrieve() .bodyToMono(Void.class); ---- -==== You can also supply form data in-line by using `BodyInserters`, as the following example shows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -435,7 +398,6 @@ You can also supply form data in-line by using `BodyInserters`, as the following .retrieve() .bodyToMono(Void.class); ---- -==== @@ -467,7 +429,6 @@ builder `part` methods. Once a `MultiValueMap` is prepared, the easiest way to pass it to the the `WebClient` is through the `syncBody` method, as the following example shows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -479,7 +440,6 @@ through the `syncBody` method, as the following example shows: .retrieve() .bodyToMono(Void.class); ---- -==== If the `MultiValueMap` contains at least one non-`String` value, which could also represent regular form data (that is, `application/x-www-form-urlencoded`), you need not @@ -489,7 +449,6 @@ set the `Content-Type` to `multipart/form-data`. This is always the case when us As an alternative to `MultipartBodyBuilder`, you can also provide multipart content, inline-style, through the built-in `BodyInserters`, as the following example shows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -501,7 +460,6 @@ inline-style, through the built-in `BodyInserters`, as the following example sho .retrieve() .bodyToMono(Void.class); ---- -==== @@ -512,7 +470,6 @@ inline-style, through the built-in `BodyInserters`, as the following example sho You can register a client filter (`ExchangeFilterFunction`) through the `WebClient.Builder` in order to intercept and modify requests, as the following example shows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -527,12 +484,10 @@ WebClient client = WebClient.builder() }) .build(); ---- -==== This can be used for cross-cutting concerns, such as authentication. The following example uses a filter for basic authentication through a static factory method: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -543,13 +498,11 @@ WebClient client = WebClient.builder() .filter(basicAuthentication("user", "password")) .build(); ---- -==== Filters apply globally to every request. To change a filter's behavior for a specific request, you can add request attributes to the `ClientRequest` that can then be accessed by all filters in the chain, as the following example shows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -567,13 +520,11 @@ client.get().uri("http://example.org/") } ---- -==== You can also replicate an existing `WebClient`, insert new filters, or remove already registered filters. The following example, inserts a basic authentication filter at index 0: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -586,7 +537,6 @@ WebClient client = webClient.mutate() }) .build(); ---- -==== diff --git a/src/docs/asciidoc/web/webflux-websocket.adoc b/src/docs/asciidoc/web/webflux-websocket.adoc index e2a9d9bf20..fd0d0810ee 100644 --- a/src/docs/asciidoc/web/webflux-websocket.adoc +++ b/src/docs/asciidoc/web/webflux-websocket.adoc @@ -26,7 +26,6 @@ server-side applications that handle WebSocket messages. To create a WebSocket server, you can first create a `WebSocketHandler`. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -41,11 +40,9 @@ The following example shows how to do so: } } ---- -==== Then you can map it to a URL and add a `WebSocketHandlerAdapter`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -69,7 +66,6 @@ Then you can map it to a URL and add a `WebSocketHandlerAdapter`, as the followi } } ---- -==== @@ -110,7 +106,6 @@ receives a cancellation signal. The most basic implementation of a handler is one that handles the inbound stream. The following example shows such an implementation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -133,7 +128,7 @@ class ExampleHandler implements WebSocketHandler { <2> Do something with each message. <3> Perform nested asynchronous operations that use the message content. <4> Return a `Mono` that completes when receiving completes. -==== + TIP: For nested, asynchronous operations, you may need to call `message.retain()` on underlying servers that use pooled data buffers (for example, Netty). Otherwise, the data buffer may be @@ -142,7 +137,6 @@ released before you have had a chance to read the data. For more background, see The following implementation combines the inbound and outbound streams: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -167,12 +161,11 @@ class ExampleHandler implements WebSocketHandler { <1> Handle the inbound message stream. <2> Create the outbound message, producing a combined flow. <3> Return a `Mono` that does not complete while we continue to receive. -==== + Inbound and outbound streams can be independent and be joined only for completion, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -200,7 +193,6 @@ class ExampleHandler implements WebSocketHandler { <1> Handle inbound message stream. <2> Send outgoing messages. <3> Join the streams and return a `Mono` that completes when either stream ends. -==== @@ -243,7 +235,6 @@ The `RequestUpgradeStrategy` for each server exposes WebSocket-related configura options available for the underlying WebSocket engine. The following example sets WebSocket options when running on Tomcat: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -263,7 +254,6 @@ WebSocket options when running on Tomcat: } } ---- -==== Check the upgrade strategy for your server to see what options are available. Currently, only Tomcat and Jetty expose such options. @@ -296,7 +286,6 @@ API to suspend receiving messages for back pressure. To start a WebSocket session, you can create an instance of the client and use its `execute` methods: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -308,7 +297,6 @@ client.execute(url, session -> .doOnNext(System.out::println) .then()); ---- -==== Some clients, such as Jetty, implement `Lifecycle` and need to be stopped and started before you can use them. All clients have constructor options related to configuration diff --git a/src/docs/asciidoc/web/webflux.adoc b/src/docs/asciidoc/web/webflux.adoc index 6ee9cd5852..9415f14f12 100644 --- a/src/docs/asciidoc/web/webflux.adoc +++ b/src/docs/asciidoc/web/webflux.adoc @@ -377,7 +377,6 @@ https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-the-Spr The code snippets below show using the `HttpHandler` adapters with each server API: -==== *Reactor Netty* [source,java,indent=0] [subs="verbatim,quotes"] @@ -433,13 +432,13 @@ server.addConnector(connector); server.start(); ---- + *Servlet 3.1+ Container* To deploy as a WAR to any Servlet 3.1+ container, you can extend and include {api-spring-framework}/web/server/adapter/AbstractReactiveWebInitializer.html[`AbstractReactiveWebInitializer`] in the WAR. That class wraps an `HttpHandler` with `ServletHttpHandlerAdapter` and registers that as a `Servlet`. -==== @@ -525,13 +524,11 @@ Spring ApplicationContext, or that can be registered directly with it: `ServerWebExchange` exposes the following method for access to form data: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- Mono> getFormData(); ---- -==== The `DefaultServerWebExchange` uses the configured `HttpMessageReader` to parse form data (`application/x-www-form-urlencoded`) into a `MultiValueMap`. By default, @@ -545,13 +542,11 @@ The `DefaultServerWebExchange` uses the configured `HttpMessageReader` to parse `ServerWebExchange` exposes the following method for access to multipart data: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- Mono> getMultipartData(); ---- -==== The `DefaultServerWebExchange` uses the configured `HttpMessageReader>` to parse `multipart/form-data` content @@ -832,7 +827,6 @@ headers are masked by default and you must explicitly enable their logging in fu The followig example shows how to do so for server-side requests: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -846,11 +840,9 @@ class MyConfig implements WebFluxConfigurer { } } ---- -==== The following example shows how to do so for client-side requests: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -861,7 +853,6 @@ WebClient webClient = WebClient.builder() .exchangeStrategies(ExchangeStrategies.builder().codecs(consumer).build()) .build(); ---- -==== @@ -893,14 +884,12 @@ Spring configuration in a WebFlux application typically contains: The configuration is given to `WebHttpHandlerBuilder` to build the processing chain, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- ApplicationContext context = ... HttpHandler handler = WebHttpHandlerBuilder.applicationContext(context); ---- -==== The resulting `HttpHandler` is ready for use with a <>. @@ -1128,7 +1117,6 @@ do not have to extend base classes nor implement specific interfaces. The following listing shows a basic example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1141,7 +1129,6 @@ The following listing shows a basic example: } } ---- -==== In the preceding example, the method returns a `String` to be written to the response body. @@ -1160,7 +1147,6 @@ a web component. To enable auto-detection of such `@Controller` beans, you can add component scanning to your Java configuration, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1172,7 +1158,7 @@ your Java configuration, as the following example shows: } ---- <1> Scan the `org.example.web` package. -==== + `@RestController` is a <> that is itself meta-annotated with `@Controller` and `@ResponseBody`, indicating a controller whose @@ -1205,7 +1191,6 @@ using `@RequestMapping`, which, by default, matches to all HTTP methods. At the The following example uses type and method level mappings: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1225,7 +1210,6 @@ The following example uses type and method level mappings: } } ---- -==== [[webflux-ann-requestmapping-uri-templates]] @@ -1241,7 +1225,6 @@ You can map requests by using glob patterns and wildcards: You can also declare URI variables and access their values with `@PathVariable`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1250,11 +1233,9 @@ as the following example shows: // ... } ---- -==== You can declare URI variables at the class and method levels, as the following example shows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -1270,7 +1251,7 @@ public class OwnerController { ---- <1> Class-level URI mapping. <2> Method-level URI mapping. -==== + URI variables are automatically converted to the appropriate type or a `TypeMismatchException` is raised. Simple types (`int`, `long`, `Date`, and so on) are supported by default and you can @@ -1289,7 +1270,6 @@ The syntax `{varName:regex}` declares a URI variable with a regular expression t syntax: `{varName:regex}`. For example, given a URL of `/spring-web-3.0.5 .jar`, the following method extracts the name, version, and file extension: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1298,7 +1278,6 @@ extracts the name, version, and file extension: // ... } ---- -==== URI path patterns can also have embedded `${...}` placeholders that are resolved on startup through `PropertyPlaceHolderConfigurer` against local, system, environment, and other property @@ -1337,7 +1316,6 @@ sorted last instead. If two patterns are both catch-all, the longer is chosen. You can narrow the request mapping based on the `Content-Type` of the request, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1346,7 +1324,6 @@ as the following example shows: // ... } ---- -==== The consumes attribute also supports negation expressions -- for example, `!text/plain` means any content type other than `text/plain`. @@ -1366,7 +1343,6 @@ TIP: `MediaType` provides constants for commonly used media types -- for example You can narrow the request mapping based on the `Accept` request header and the list of content types that a controller method produces, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1376,7 +1352,6 @@ content types that a controller method produces, as the following example shows: // ... } ---- -==== The media type can specify a character set. Negated expressions are supported -- for example, `!text/plain` means any content type other than `text/plain`. @@ -1402,7 +1377,6 @@ You can narrow request mappings based on query parameter conditions. You can tes presence of a query parameter (`myParam`), for its absence (`!myParam`), or for a specific value (`myParam=myValue`). The following examples tests for a parameter with a value: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1412,11 +1386,10 @@ specific value (`myParam=myValue`). The following examples tests for a parameter } ---- <1> Check that `myParam` equals `myValue`. -==== + You can also use the same with request header conditions, as the follwing example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1426,7 +1399,7 @@ You can also use the same with request header conditions, as the follwing exampl } ---- <1> Check that `myHeader` equals `myValue`. -==== + [[webflux-ann-requestmapping-head-options]] @@ -1479,7 +1452,6 @@ You can programmatically register Handler methods, which can be used for dynamic registrations or for advanced cases, such as different instances of the same handler under different URLs. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1504,7 +1476,6 @@ public class MyConfig { <2> Prepare the request mapping metadata. <3> Get the handler method. <4> Add the registration. -==== @@ -1745,7 +1716,6 @@ to mask variable content. That said, if you want to access matrix variables from controller method, you need to add a URI variable to the path segment where matrix variables are expected. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1758,13 +1728,11 @@ variables are expected. The following example shows how to do so: // q == 11 } ---- -==== Given that all path segments can contain matrix variables, you may sometimes need to disambiguate which path variable the matrix variable is expected to be in, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1779,12 +1747,10 @@ as the following example shows: // q2 == 22 } ---- -==== You can define a matrix variable may be defined as optional and specify a default value as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1796,11 +1762,9 @@ as the following example shows: // q == 1 } ---- -==== To get all matrix variables, use a `MultiValueMap`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1815,7 +1779,6 @@ To get all matrix variables, use a `MultiValueMap`, as the following example sho // petMatrixVars: ["q" : 22, "s" : 23] } ---- -==== [[webflux-ann-requestparam]] @@ -1825,7 +1788,6 @@ To get all matrix variables, use a `MultiValueMap`, as the following example sho You can use the `@RequestParam` annotation to bind query parameters to a method argument in a controller. The following code snippet shows the usage: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1847,7 +1809,7 @@ controller. The following code snippet shows the usage: } ---- <1> Using `@RequestParam`. -==== + TIP: The Servlet API "`request parameter`" concept conflates query parameters, form data, and multiparts into one. However, in WebFlux, each is accessed individually through @@ -1882,7 +1844,6 @@ controller. The following example shows a request with headers: -==== [literal] [subs="verbatim,quotes"] ---- @@ -1893,11 +1854,9 @@ Accept-Encoding gzip,deflate Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive 300 ---- -==== The following example gets the value of the `Accept-Encoding` and `Keep-Alive` headers: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1910,7 +1869,7 @@ The following example gets the value of the `Accept-Encoding` and `Keep-Alive` h ---- <1> Get the value of the `Accept-Encoging` header. <2> Get the value of the `Keep-Alive` header. -==== + Type conversion is applied automatically if the target method parameter type is not `String`. See <>. @@ -1934,17 +1893,14 @@ in a controller. The following example shows a request with a cookie: -==== [literal] [subs="verbatim,quotes"] ---- JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84 ---- -==== The following code sample demonstrates how to get the cookie value: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1954,7 +1910,7 @@ The following code sample demonstrates how to get the cookie value: } ---- <1> Get the cookie value. -==== + Type conversion is applied automatically if the target method parameter type is not `String`. See <>. @@ -1970,7 +1926,6 @@ the values of query parameters and form fields whose names match to field names. referred to as data binding, and it saves you from having to deal with parsing and converting individual query parameters and form fields. The following example binds an instance of `Pet`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1978,7 +1933,7 @@ converting individual query parameters and form fields. The following example bi public String processSubmit(@ModelAttribute Pet pet) { } <1> ---- <1> Bind an instance of `Pet`. -==== + The `Pet` instance in the preceding example is resolved as follows: @@ -2000,7 +1955,6 @@ Data binding can result in errors. By default, a `WebExchangeBindException` is r to check for such errors in the controller method, you can add a `BindingResult` argument immediately next to the `@ModelAttribute`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2013,14 +1967,13 @@ immediately next to the `@ModelAttribute`, as the following example shows: } ---- <1> Adding a `BindingResult`. -==== + You can automatically apply validation after data binding by adding the `javax.validation.Valid` annotation or Spring's `@Validated` annotation (see also <> and <>). The following example uses the `@Valid` annotation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2033,7 +1986,7 @@ You can automatically apply validation after data binding by adding the } ---- <1> Using `@Valid` on a model attribute argument. -==== + Spring WebFlux, unlike Spring MVC, supports reactive types in the model -- for example, `Mono` or `io.reactivex.Single`. You can declare a `@ModelAttribute` argument @@ -2043,7 +1996,6 @@ argument, you must declare the `@ModelAttribute` argument before it without a re type wrapper, as shown earlier. Alternatively, you can handle any errors through the reactive type, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2058,7 +2010,6 @@ reactive type, as the following example shows: }); } ---- -==== Note that use of `@ModelAttribute` is optional -- for example, to set its attributes. By default, any argument that is not a simple value type( as determined by @@ -2079,7 +2030,6 @@ requests to access. Consider the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2090,14 +2040,13 @@ Consider the following example: } ---- <1> Using the `@SessionAttributes` annotation. -==== + On the first request, when a model attribute with the name, `pet`, is added to the model, it is automatically promoted to and saved in the `WebSession`. It remains there until another controller method uses a `SessionStatus` method argument to clear the storage, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2120,7 +2069,7 @@ as the following example shows: ---- <1> Using the `@SessionAttributes` annotation. <2> Using a `SessionStatus` variable. -==== + [[webflux-ann-sessionattribute]] @@ -2131,7 +2080,6 @@ If you need access to pre-existing session attributes that are managed globally (that is, outside the controller -- for example, by a filter) and may or may not be present, you can use the `@SessionAttribute` annotation on a method parameter, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2141,7 +2089,7 @@ you can use the `@SessionAttribute` annotation on a method parameter, as the fol } ---- <1> Using `@SessionAttribute`. -==== + For use cases that require adding or removing session attributes, consider injecting `WebSession` into the controller method. @@ -2152,14 +2100,13 @@ workflow, consider using `SessionAttributes`, as described in [[webflux-ann-requestattrib]] -==== `@RequestAttribute` [.small]#<># + Similarly to `@SessionAttribute`, you can use the `@RequestAttribute` annotation to access pre-existing request attributes created earlier (for example, by a `WebFilter`), as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2169,7 +2116,7 @@ as the following example shows: } ---- <1> Using `@RequestAttribute`. -==== + [[webflux-multipart-forms]] @@ -2181,7 +2128,6 @@ content. The best way to handle a file upload form (for example, from a browser) is through data binding to a <>, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2205,12 +2151,10 @@ public class FileUploadController { } ---- -==== You can also submit multipart requests from non-browser clients in a RESTful service scenario. The following example uses a file along with JSON: -==== [literal] [subs="verbatim,quotes"] ---- @@ -2231,11 +2175,9 @@ Content-Type: text/xml Content-Transfer-Encoding: 8bit ... File Data ... ---- -==== You can access individual parts with `@RequestPart`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2247,12 +2189,11 @@ You can access individual parts with `@RequestPart`, as the following example sh ---- <1> Using `@RequestPart` to get the metadata. <2> Using `@RequestPart` to get the file. -==== + To deserialize the raw part content (for example, to JSON -- similar to `@RequestBody`), you can declare a concrete target `Object`, instead of `Part`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2262,7 +2203,7 @@ you can declare a concrete target `Object`, instead of `Part`, as the following } ---- <1> Using `@RequestPart` to get the metadata. -==== + You can use `@RequestPart` combination with `javax.validation.Valid` or Spring's `@Validated` annotation, which causes Standard Bean Validation to be applied. @@ -2270,7 +2211,6 @@ By default, validation errors cause a `WebExchangeBindException`, which is turne into a 400 (`BAD_REQUEST`) response. Alternatively, you can handle validation errors locally within the controller through an `Errors` or `BindingResult` argument, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2282,12 +2222,11 @@ public String handle(@Valid @RequestPart("meta-data") MetaData metadata, <1> ---- <1> Using a `@Valid` annotation. <2> Using a `BindingResult` argument. -==== + To access all multipart data as a `MultiValueMap`, you can use `@RequestBody`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2297,12 +2236,11 @@ as the following example shows: } ---- <1> Using `@RequestBody`. -==== + To access multipart data sequentially, in streaming fashion, you can use `@RequestBody` with `Flux` instead, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2312,7 +2250,7 @@ To access multipart data sequentially, in streaming fashion, you can use `@Reque } ---- <1> Using `@RequestBody`. -==== + [[webflux-ann-requestbody]] @@ -2323,7 +2261,6 @@ You can use the `@RequestBody` annotation to have the request body read and dese `Object` through an <>. The following example uses a `@RequestBody` argument: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2332,13 +2269,11 @@ The following example uses a `@RequestBody` argument: // ... } ---- -==== Unlike Spring MVC, in WebFlux, the `@RequestBody` method argument supports reactive types and fully non-blocking reading and (client-to-server) streaming. The following example uses a `Mono`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2347,7 +2282,6 @@ uses a `Mono`: // ... } ---- -==== You can use the <> option of the <> to configure or customize message readers. @@ -2359,7 +2293,6 @@ into a 400 (`BAD_REQUEST`) response. Alternatively, you can handle validation er within the controller through an `Errors` or a `BindingResult` argument. The following example uses a `BindingResult` argument`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2368,7 +2301,6 @@ example uses a `BindingResult` argument`: // ... } ---- -==== [[webflux-ann-httpentity]] @@ -2379,7 +2311,6 @@ example uses a `BindingResult` argument`: container object that exposes request headers and the body. The following example uses an `HttpEntity`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2388,7 +2319,6 @@ container object that exposes request headers and the body. The following exampl // ... } ---- -==== [[webflux-ann-responsebody]] @@ -2398,7 +2328,6 @@ container object that exposes request headers and the body. The following exampl You can use the `@ResponseBody` annotation on a method to have the return serialized to the response body through an <>. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2408,7 +2337,6 @@ response body through an <>. The following exa // ... } ---- -==== `@ResponseBody` is also supported at the class level, in which case it is inherited by all controller methods. This is the effect of `@RestController`, which is nothing more @@ -2432,7 +2360,6 @@ configure or customize message writing. `ResponseEntity` is like <> but with status and headers. For example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2443,7 +2370,6 @@ configure or customize message writing. return ResponseEntity.ok().eTag(etag).build(body); } ---- -==== WebFlux supports using a single value <> to produce the `ResponseEntity` asynchronously, and/or single and multi-value reactive types @@ -2465,7 +2391,6 @@ which allows rendering only a subset of all fields in an `Object`. To use it wit `@ResponseBody` or `ResponseEntity` controller methods, you can use Jackson's `@JsonView` annotation to activate a serialization view class, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2506,7 +2431,6 @@ which allows rendering only a subset of all fields in an `Object`. To use it wit } } ---- -==== NOTE: `@JsonView` allows an array of view classes but you can only specify only one per controller method. Use a composite interface if you need to activate multiple views. @@ -2538,7 +2462,6 @@ related to the request body). The following example uses a `@ModelAttribute` method: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2548,11 +2471,9 @@ The following example uses a `@ModelAttribute` method: // add more ... } ---- -==== The following example adds one attribute only: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2561,7 +2482,6 @@ The following example adds one attribute only: return accountRepository.findAccount(number); } ---- -==== NOTE: When a name is not explicitly specified, a default name is chosen based on the type, as explained in the javadoc for {api-spring-framework}/core/Conventions.html[`Conventions`]. @@ -2574,7 +2494,6 @@ attributes can be transparently resolved (and the model updated) to their actual at the time of `@RequestMapping` invocation, provided a `@ModelAttribute` argument is declared without a wrapper, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2589,7 +2508,6 @@ declared without a wrapper, as the following example shows: // ... } ---- -==== In addition, any model attributes that have a reactive type wrapper are resolved to their actual values (and the model updated) just prior to view rendering. @@ -2601,7 +2519,6 @@ controllers, unless the return value is a `String` that would otherwise be inter as a view name. `@ModelAttribute` can also help to customize the model attribute name, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2612,7 +2529,6 @@ as the following example shows: return account; } ---- -==== @@ -2638,7 +2554,6 @@ do, except for `@ModelAttribute` (command object) arguments. Typically, they are with a `WebDataBinder` argument, for registrations, and a `void` return value. The following example uses the `@InitBinder` annotation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2656,13 +2571,12 @@ The following example uses the `@InitBinder` annotation: } ---- <1> Using the `@InitBinder` annotation. -==== + Alternatively, when using a `Formatter`-based setup through a shared `FormattingConversionService`, you could re-use the same approach and register controller-specific `Formatter` instances, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2678,7 +2592,7 @@ controller-specific `Formatter` instances, as the following example shows: } ---- <1> Adding a custom formatter (a `DateFormatter`, in this case). -==== + @@ -2690,7 +2604,6 @@ controller-specific `Formatter` instances, as the following example shows: `@ExceptionHandler` methods to handle exceptions from controller methods. The following example includes such a handler method: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2706,7 +2619,7 @@ example includes such a handler method: } ---- <1> Declaring an `@ExceptionHandler`: -==== + The exception can match against a top-level exception being propagated (that is, a direct `IOException` being thrown) or against the immediate cause within a top-level wrapper exception @@ -2770,7 +2683,6 @@ By default `@ControllerAdvice` methods apply to every request (that is, all cont you can narrow that down to a subset of controllers through attributes on the annotation, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2786,7 +2698,6 @@ as the following example shows: @ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class}) public class ExampleAdvice3 {} ---- -==== The preceding selectors are evaluated at runtime and may negatively impact performance if you use them extensively. See the @@ -2860,7 +2771,6 @@ While https://tools.ietf.org/html/rfc7234#section-5.2.2[RFC 7234] describes all directives for the `Cache-Control` response header, the `CacheControl` type takes a use case-oriented approach that focuses on the common scenarios, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2875,7 +2785,6 @@ use case-oriented approach that focuses on the common scenarios, as the followin // "Cache-Control: max-age=864000, public, no-transform" CacheControl ccCustom = CacheControl.maxAge(10, TimeUnit.DAYS).noTransform().cachePublic(); ---- -==== @@ -2888,7 +2797,6 @@ Controllers can add explicit support for HTTP caching. We recommend doing so, si against conditional request headers. A controller can add an `ETag` and `Cache-Control` settings to a `ResponseEntity`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2905,7 +2813,6 @@ settings to a `ResponseEntity`, as the following example shows: .body(book); } ---- -==== The preceding example sends a 304 (NOT_MODIFIED) response with an empty body if the comparison to the conditional request headers indicates the content has not changed. Otherwise, the @@ -2914,7 +2821,6 @@ to the conditional request headers indicates the content has not changed. Otherw You can also make the check against conditional request headers in the controller, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2935,7 +2841,7 @@ as the following example shows: <1> Application-specific calculation. <2> Response has been set to 304 (NOT_MODIFIED). No further processing. <3> Continue with request processing. -==== + There are three variants for checking conditional requests against `eTag` values, `lastModified` values, or both. For conditional `GET` and `HEAD` requests, you can set the response to @@ -2976,7 +2882,6 @@ gain full control over the configuration through the You can use the `@EnableWebFlux` annotation in your Java config, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2985,7 +2890,6 @@ You can use the `@EnableWebFlux` annotation in your Java config, as the followin public class WebConfig { } ---- -==== The preceding example registers a number of Spring WebFlux <> and adapts to dependencies @@ -3000,7 +2904,6 @@ available on the classpath -- for JSON, XML, and others. In your Java configuration, you can implement the `WebFluxConfigurer` interface, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3012,7 +2915,6 @@ as the following example shows: } ---- -==== @@ -3026,7 +2928,6 @@ formatting library is also installed if Joda-Time is present on the classpath. The following example shows how to register custom formatters and converters: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3041,7 +2942,6 @@ The following example shows how to register custom formatters and converters: } ---- -==== NOTE: See <> and the `FormattingConversionServiceFactoryBean` for more information on when to use `FormatterRegistrar` implementations. @@ -3060,7 +2960,6 @@ as a global <> for use with `@Valid` and `Validat In your Java configuration, you can customize the global `Validator` instance, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3075,12 +2974,10 @@ as the following example shows: } ---- -==== Note that you can also register `Validator` implementations locally, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3094,7 +2991,6 @@ as the following example shows: } ---- -==== TIP: If you need to have a `LocalValidatorFactoryBean` injected somewhere, create a bean and mark it with `@Primary` in order to avoid conflict with the one declared in the MVC config. @@ -3111,7 +3007,6 @@ can also enable a query parameter-based strategy. The following example shows how to customize the requested content type resolution: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3125,7 +3020,6 @@ The following example shows how to customize the requested content type resoluti } } ---- -==== @@ -3135,7 +3029,6 @@ The following example shows how to customize the requested content type resoluti The following example shows how to customize how the request and response body are read and written: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3149,7 +3042,6 @@ The following example shows how to customize how the request and response body a } } ---- -==== `ServerCodecConfigurer` provides a set of default readers and writers. You can use it to add more readers and writers, customize the default ones, or replace the default ones completely. @@ -3176,7 +3068,6 @@ It also automatically registers the following well-known modules if they are det The following example shows how to configure view resolution: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3190,13 +3081,11 @@ The following example shows how to configure view resolution: } } ---- -==== The `ViewResolverRegistry` has shortcuts for view technologies with which the Spring Framework integrates. The following example uses FreeMarker (which also requires configuring the underlying FreeMarker view technology): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3220,11 +3109,9 @@ underlying FreeMarker view technology): } } ---- -==== You can also plug in any `ViewResolver` implementation, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3240,14 +3127,12 @@ You can also plug in any `ViewResolver` implementation, as the following example } } ---- -==== To support <> and rendering other formats through view resolution (besides HTML), you can configure one or more default views based on the `HttpMessageWriterView` implementation, which accepts any of the available <> from `spring-web`. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3267,7 +3152,6 @@ on the `HttpMessageWriterView` implementation, which accepts any of the availabl // ... } ---- -==== See <> for more on the view technologies that are integrated with Spring WebFlux. @@ -3287,7 +3171,6 @@ and a reduction in HTTP requests made by the browser. The `Last-Modified` header evaluated and, if present, a `304` status code is returned. The following list shows the example: -==== [source,java,indent=0] [subs="verbatim"] ---- @@ -3304,7 +3187,6 @@ the example: } ---- -==== // TODO: See also <>. @@ -3320,7 +3202,6 @@ JavaScript resources used with a module loader). The following example shows how to use `VersionResourceResolver` in your Java configuration: -==== [source,java,indent=0] [subs="verbatim"] ---- @@ -3338,7 +3219,6 @@ The following example shows how to use `VersionResourceResolver` in your Java co } ---- -==== You can use `ResourceUrlProvider` to rewrite URLs and apply the full chain of resolvers and transformers (for example, to insert versions). The WebFlux configuration provides a `ResourceUrlProvider` @@ -3369,7 +3249,6 @@ You can customize options related to path matching. For details on the individua {api-spring-framework}/web/reactive/config/PathMatchConfigurer.html[`PathMatchConfigurer`] javadoc. The following example shows how to use `PathMatchConfigurer`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3388,7 +3267,6 @@ The following example shows how to use `PathMatchConfigurer`: } ---- -==== [TIP] ==== @@ -3419,7 +3297,6 @@ For advanced mode, you can remove `@EnableWebFlux` and extend directly from `DelegatingWebFluxConfiguration` instead of implementing `WebFluxConfigurer`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3430,7 +3307,6 @@ as the following example shows: } ---- -==== You can keep existing methods in `WebConfig`, but you can now also override bean declarations from the base class and still have any number of other `WebMvcConfigurer` implementations on diff --git a/src/docs/asciidoc/web/webmvc-cors.adoc b/src/docs/asciidoc/web/webmvc-cors.adoc index 144edaa56c..633bb1db3e 100644 --- a/src/docs/asciidoc/web/webmvc-cors.adoc +++ b/src/docs/asciidoc/web/webmvc-cors.adoc @@ -83,7 +83,6 @@ The {api-spring-framework}/web/bind/annotation/CrossOrigin.html[`@CrossOrigin`] annotation enables cross-origin requests on annotated controller methods, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -103,7 +102,6 @@ public class AccountController { } } ---- -==== By default, `@CrossOrigin` allows: @@ -120,7 +118,6 @@ should only be used where appropriate. `@CrossOrigin` is supported at the class level, too, and is inherited by all methods, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -140,12 +137,10 @@ public class AccountController { } } ---- -==== You can use `@CrossOrigin` at both the class level and the method level, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -166,7 +161,6 @@ public class AccountController { } } ---- -==== @@ -202,7 +196,6 @@ should only be used where appropriate. To enable CORS in the MVC Java config, you can use the `CorsRegistry` callback, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -224,7 +217,6 @@ public class WebConfig implements WebMvcConfigurer { } } ---- -==== @@ -234,7 +226,6 @@ public class WebConfig implements WebMvcConfigurer { To enable CORS in the XML namespace, you can use the `` element, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -252,7 +243,6 @@ as the following example shows: ---- -==== @@ -272,7 +262,6 @@ for CORS. To configure the filter, pass a `CorsConfigurationSource` to its constructor, as the following example shows: -==== [source,java,indent=0] [subs="verbatim"] ---- @@ -291,4 +280,3 @@ source.registerCorsConfiguration("/**", config); CorsFilter filter = new CorsFilter(source); ---- -==== diff --git a/src/docs/asciidoc/web/webmvc-view.adoc b/src/docs/asciidoc/web/webmvc-view.adoc index 2959121733..9bfd82eb65 100644 --- a/src/docs/asciidoc/web/webmvc-view.adoc +++ b/src/docs/asciidoc/web/webmvc-view.adoc @@ -46,7 +46,6 @@ integration for using Spring MVC with FreeMarker templates. The following example shows how to configure FreeMarker as a view technology: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -69,11 +68,9 @@ The following example shows how to configure FreeMarker as a view technology: } } ---- -==== The following example shows how to configure the same in XML: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -88,12 +85,10 @@ The following example shows how to configure the same in XML: ---- -==== Alternatively, you can also declare the `FreeMarkerConfigurer` bean for full control over all properties, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -101,7 +96,6 @@ properties, as the following example shows: ---- -==== Your templates need to be stored in the directory specified by the `FreeMarkerConfigurer` shown in the preceding example. Given the preceding configuration, if your controller returns a view name @@ -119,7 +113,6 @@ the `FreeMarkerConfigurer` bean. The `freemarkerSettings` property requires a `java.util.Properties` object, and the `freemarkerVariables` property requires a `java.util.Map`. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -134,7 +127,6 @@ the `FreeMarkerConfigurer` bean. The `freemarkerSettings` property requires a ---- -==== See the FreeMarker documentation for details of settings and variables as they apply to the `Configuration` object. @@ -173,7 +165,6 @@ controller, you can use code similar to the next example to bind to field values display error messages for each input field in similar fashion to the JSP equivalent. The following example shows the `personForm` view that was configured earlier: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -196,7 +187,6 @@ The following example shows the `personForm` view that was configured earlier: ... ---- -==== `<@spring.bind>` requires a 'path' argument, which consists of the name of your command object (it is 'command', unless you changed it in your `FormController` properties) @@ -318,14 +308,12 @@ time, a class name or style attribute. Note that FreeMarker can specify default values for the attributes parameter. The following example shows how to use the `formInput` and `showWErrors` macros: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- <@spring.formInput "command.name"/> <@spring.showErrors "
"/> ---- -==== The next example shows the output of the form fragment, generating the name field and displaying a validation error after the form was submitted with no value in the field. Validation @@ -333,7 +321,6 @@ occurs through Spring's Validation framework. The generated HTML resembles the following example: -==== [source,jsp,indent=0] [subs="verbatim,quotes"] ---- @@ -344,7 +331,6 @@ The generated HTML resembles the following example:

---- -==== The `formTextarea` macro works the same way as the `formInput` macro and accepts the same parameter list. Commonly, the second parameter (attributes) is used to pass style @@ -370,7 +356,6 @@ value of 'London' for this field, so no validation is necessary. When the form i rendered, the entire list of cities to choose from is supplied as reference data in the model under the name 'cityMap'. The following listing shows the example: -==== [source,jsp,indent=0] [subs="verbatim,quotes"] ---- @@ -378,7 +363,6 @@ model under the name 'cityMap'. The following listing shows the example: Town: <@spring.formRadioButtons "command.address.town", cityMap, ""/>

---- -==== The preceding listing renders a line of radio buttons, one for each value in `cityMap`, and uses a separator of `""`. No additional attributes are supplied (the last parameter to the macro is @@ -387,7 +371,6 @@ keys are what the form actually submits as POSTed request parameters. The map va labels that the user sees. In the preceding example, given a list of three well known cities and a default value in the form backing object, the HTML resembles the following: -==== [source,jsp,indent=0] [subs="verbatim,quotes"] ---- @@ -396,12 +379,10 @@ and a default value in the form backing object, the HTML resembles the following Paris New York ---- -==== If your application expects to handle cities by internal codes (for example), you can create the map of codes with suitable keys, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -416,12 +397,10 @@ codes with suitable keys, as the following example shows: return model; } ---- -==== The code now produces output where the radio values are the relevant codes, but the user still sees the more user-friendly city names, as follows: -==== [source,jsp,indent=0] [subs="verbatim,quotes"] ---- @@ -430,7 +409,6 @@ user still sees the more user-friendly city names, as follows: Paris New York ---- -==== [[mvc-views-form-macros-html-escaping]] @@ -447,21 +425,18 @@ template processing to provide different behavior for different fields in your f To switch to XHTML compliance for your tags, specify a value of `true` for a model or context variable named `xhtmlCompliant`, as the following example shows: -==== [source,jsp,indent=0] [subs="verbatim,quotes"] ---- <#-- for FreeMarker --> <#assign xhtmlCompliant = true> ---- -==== After processing this directive, any elements generated by the Spring macros are now XHTML compliant. In similar fashion, you can specify HTML escaping per field, as the following example shows: -==== [source,jsp,indent=0] [subs="verbatim,quotes"] ---- @@ -474,7 +449,6 @@ In similar fashion, you can specify HTML escaping per field, as the following ex <#assign htmlEscape = false in spring> <#-- all future fields will be bound with HTML escaping off --> ---- -==== @@ -496,7 +470,6 @@ NOTE: The Groovy Markup Template engine requires Groovy 2.3.1+. The following example shows how to configure the Groovy Markup Template Engine: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -519,11 +492,9 @@ The following example shows how to configure the Groovy Markup Template Engine: } } ---- -==== The following example shows how to configure the same in XML: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -536,7 +507,6 @@ The following example shows how to configure the same in XML: ---- -==== @@ -546,7 +516,6 @@ The following example shows how to configure the same in XML: Unlike traditional template engines, Groovy Markup relies on a DSL that uses a builder syntax. The following example shows a sample template for an HTML page: -==== [source,groovy,indent=0] [subs="verbatim,quotes"] ---- @@ -561,7 +530,6 @@ syntax. The following example shows a sample template for an HTML page: } } ---- -==== @@ -620,7 +588,6 @@ You can declare a `ScriptTemplateConfigurer` bean to specify the script engine t the script files to load, what function to call to render templates, and so on. The following example uses Mustache templates and the Nashorn JavaScript engine: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -644,11 +611,9 @@ The following example uses Mustache templates and the Nashorn JavaScript engine: } } ---- -==== The following example shows the same arrangement in XML: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -662,11 +627,9 @@ The following example shows the same arrangement in XML: ---- -==== The controller would look no different for the Java and XML configurations, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -681,11 +644,9 @@ The controller would look no different for the Java and XML configurations, as t } } ---- -==== The following example shows the Mustache template: -==== [source,html,indent=0] [subs="verbatim,quotes"] ---- @@ -698,7 +659,6 @@ The following example shows the Mustache template: ---- -==== The render function is called with the following parameters: @@ -719,7 +679,6 @@ browser facilities that are not available in the server-side script engine. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -743,7 +702,6 @@ The following example shows how to do so: } } ---- -==== NOTE: Setting the `sharedEngine` property to `false` is required when you use non-thread-safe script engines with templating libraries not designed for concurrency, such as Handlebars or @@ -752,20 +710,17 @@ to https://bugs.openjdk.java.net/browse/JDK-8076099[this bug]. `polyfill.js` defines only the `window` object needed by Handlebars to run properly, as follows: -==== [source,javascript,indent=0] [subs="verbatim,quotes"] ---- var window = {}; ---- -==== This basic `render.js` implementation compiles the template before using it. A production-ready implementation should also store any reused cached templates or pre-compiled templates. You can do so on the script side (and handle any customization you need -- managing template engine configuration, for example). The following example shows how to do so: -==== [source,javascript,indent=0] [subs="verbatim,quotes"] ---- @@ -774,7 +729,6 @@ template engine configuration, for example). The following example shows how to return compiledTemplate(model); } ---- -==== Check out the Spring Framework unit tests, https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc/src/test/java/org/springframework/web/servlet/view/script[Java], and @@ -801,7 +755,6 @@ When developing with JSPs, you can declare a `InternalResourceViewResolver` or a mapped to a class and a URL. With a `ResourceBundleViewResolver`, you can mix different types of views byusing only one resolver, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -831,7 +784,6 @@ directory so there can be no direct access by clients.
---- -==== @@ -884,14 +836,12 @@ called `spring-form.tld`. To use the tags from this library, add the following directive to the top of your JSP page: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> ---- where `form` is the tag name prefix you want to use for the tags from this library. -==== [[mvc-view-jsp-formtaglib-formtag]] @@ -907,7 +857,6 @@ such as `firstName` and `lastName`. We can use it as the form-backing object of form controller, which returns `form.jsp`. The following example shows what `form.jsp` could look like: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -929,7 +878,6 @@ look like: ---- -==== The `firstName` and `lastName` values are retrieved from the command object placed in the `PageContext` by the page controller. Keep reading to see more complex examples of @@ -937,7 +885,6 @@ how inner tags are used with the `form` tag. The following listing shows the generated HTML, which looks like a standard form: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -959,14 +906,12 @@ The following listing shows the generated HTML, which looks like a standard form ---- -==== The preceding JSP assumes that the variable name of the form-backing object is `command`. If you have put the form-backing object into the model under another name (definitely a best practice), you can bind the form to the named variable, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -988,7 +933,6 @@ following example shows: ---- -==== [[mvc-view-jsp-formtaglib-inputtag]] @@ -1008,7 +952,6 @@ This tag renders an HTML `input` tag with the `type` set to `checkbox`. Assume that our `User` has preferences such as newsletter subscription and a list of hobbies. The following example shows the `Preferences` class: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1043,11 +986,9 @@ hobbies. The following example shows the `Preferences` class: } } ---- -==== The corresponding `form.jsp` could then resemble the following: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1079,7 +1020,6 @@ The corresponding `form.jsp` could then resemble the following: ---- -==== There are three approaches to the `checkbox` tag, which should meet all your checkbox needs. @@ -1095,7 +1035,6 @@ There are three approaches to the `checkbox` tag, which should meet all your che Note that, regardless of the approach, the same HTML structure is generated. The following HTML snippet defines some checkboxes: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1111,7 +1050,6 @@ HTML snippet defines some checkboxes: ---- -==== You might not expect to see the additional hidden field after each checkbox. When a checkbox in an HTML page is not checked, its value is not sent to the @@ -1137,7 +1075,6 @@ the available options in the `items` property. Typically, the bound property is collection so that it can hold multiple values selected by the user. The following example shows a JSP that uses this tag: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1153,7 +1090,6 @@ shows a JSP that uses this tag: ---- -==== This example assumes that the `interestList` is a `List` available as a model attribute that contains strings of the values to be selected from. If you use a `Map`, @@ -1171,7 +1107,6 @@ This tag renders an HTML `input` element with the `type` set to `radio`. A typical usage pattern involves multiple tag instances bound to the same property but with different values, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1183,7 +1118,6 @@ but with different values, as the following example shows: ---- -==== @@ -1200,7 +1134,6 @@ entry's value are used as the label to be displayed. You can also use a custom object where you can provide the property names for the value by using `itemValue` and the label by using `itemLabel`, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1209,7 +1142,6 @@ label by using `itemLabel`, as the following example shows: ---- -==== [[mvc-view-jsp-formtaglib-passwordtag]] @@ -1217,7 +1149,6 @@ label by using `itemLabel`, as the following example shows: This tag renders an HTML `input` tag with the type set to `password` with the bound value. -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1228,13 +1159,11 @@ This tag renders an HTML `input` tag with the type set to `password` with the bo ---- -==== Note that, by default, the password value is not shown. If you do want the password value to be shown, you can set the value of the `showPassword` attribute to `true`, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1245,7 +1174,6 @@ password value to be shown, you can set the value of the `showPassword` attribut ---- -==== [[mvc-view-jsp-formtaglib-selecttag]] @@ -1256,7 +1184,6 @@ option as well as the use of nested `option` and `options` tags. Assume that a `User` has a list of skills. The corresponding HTML could be as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1265,12 +1192,10 @@ Assume that a `User` has a list of skills. The corresponding HTML could be as fo ---- -==== If the `User's` skill are in Herbology, the HTML source of the 'Skills' row could be as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1285,7 +1210,6 @@ as follows: ---- -==== @@ -1295,7 +1219,6 @@ as follows: This tag renders an HTML `option` element. It sets `selected`, based on the bound value. The following HTML shows typical output for it: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1311,12 +1234,10 @@ value. The following HTML shows typical output for it: ---- -==== If the `User's` house was in Gryffindor, the HTML source of the 'House' row would be as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1333,7 +1254,6 @@ as follows: ---- <1> Note the addition of a `selected` attribute. -==== @@ -1343,7 +1263,6 @@ as follows: This tag renders a list of HTML `option` elements. It sets the `selected` attribute, based on the bound value. The following HTML shows typical output for it: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1357,11 +1276,9 @@ based on the bound value. The following HTML shows typical output for it: ---- -==== If the `User` lived in the UK, the HTML source of the 'Country' row would be as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1378,7 +1295,7 @@ If the `User` lived in the UK, the HTML source of the 'Country' row would be as ---- <1> Note the addition of a `selected` attribute. -==== + As the preceding example shows, the combined usage of an `option` tag with the `options` tag generates the same standard HTML but lets you explicitly specify a value in the @@ -1400,7 +1317,6 @@ the item label property applies to the map value. This tag renders an HTML `textarea` element. The following HTML shows typical output for it: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1410,7 +1326,6 @@ This tag renders an HTML `textarea` element. The following HTML shows typical ou ---- -==== [[mvc-view-jsp-formtaglib-hiddeninputtag]] @@ -1420,24 +1335,20 @@ This tag renders an HTML `input` tag with the `type` set to `hidden` with the bo an unbound hidden value, use the HTML `input` tag with the `type` set to `hidden`. The following HTML shows typical output for it: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== If we choose to submit the `house` value as a hidden one, the HTML would be as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== [[mvc-view-jsp-formtaglib-errorstag]] @@ -1451,7 +1362,6 @@ Assume that we want to display all error messages for the `firstName` and `lastN fields once we submit the form. We have a validator for instances of the `User` class called `UserValidator`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1467,11 +1377,9 @@ called `UserValidator`, as the following example shows: } } ---- -==== The `form.jsp` could be as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1498,12 +1406,10 @@ The `form.jsp` could be as follows: ---- -==== If we submit a form with empty values in the `firstName` and `lastName` fields, the HTML would be as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1530,7 +1436,6 @@ the HTML would be as follows: ---- -==== What if we want to display the entire list of errors for a given page? The next example shows that the `errors` tag also supports some basic wildcarding functionality. @@ -1542,7 +1447,6 @@ shows that the `errors` tag also supports some basic wildcarding functionality. The following example displays a list of errors at the top of the page, followed by field-specific errors next to the fields: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1567,11 +1471,9 @@ field-specific errors next to the fields: ---- -==== The HTML would be as follows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1597,7 +1499,6 @@ The HTML would be as follows: ---- -==== The `spring-form.tld` tag library descriptor (TLD) is included in the `spring-webmvc.jar`. For a comprehensive reference on individual tags, browse the @@ -1628,7 +1529,6 @@ To support HTTP method conversion, the Spring MVC form tag was updated to suppor the HTTP method. For example, the following snippet comes from the Pet Clinic sample: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1636,13 +1536,11 @@ sample:

---- -==== The preceding example perform an HTTP POST, with the "`real`" DELETE method hidden behind a request parameter. It is picked up by the `HiddenHttpMethodFilter`, which is defined in web.xml, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1656,11 +1554,9 @@ web.xml, as the following example shows: petclinic ---- -==== The following example shows the corresponding `@Controller` method: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1670,7 +1566,6 @@ The following example shows the corresponding `@Controller` method: return "redirect:/owners/" + ownerId; } ---- -==== [[mvc-view-jsp-formtaglib-html5]] @@ -1715,7 +1610,6 @@ To be able to use Tiles, you have to configure it by using files that contain de http://tiles.apache.org[]). In Spring, this is done by using the `TilesConfigurer`. The following example `ApplicationContext` configuration shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1731,7 +1625,6 @@ The following example `ApplicationContext` configuration shows how to do so:
---- -==== The preceding example defines five files that contain definitions. The files are all located in the `WEB-INF/defs` directory. At initialization of the `WebApplicationContext`, the @@ -1744,7 +1637,6 @@ implementations, the `UrlBasedViewResolver` and the `ResourceBundleViewResolver` You can specify locale-specific Tiles definitions by adding an underscore and then the locale, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1757,7 +1649,6 @@ the locale, as the following example shows:
---- -==== With the preceding configuration, `tiles_fr_FR.xml` is used for requests with the `fr_FR` locale, and `tiles.xml` is used by default. @@ -1773,7 +1664,6 @@ them otherwise in the file names for Tiles definitions. The `UrlBasedViewResolver` instantiates the given `viewClass` for each view it has to resolve. The following bean defines a `UrlBasedViewResolver`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1781,7 +1671,6 @@ resolve. The following bean defines a `UrlBasedViewResolver`: ---- -==== [[mvc-view-tiles-resource]] @@ -1792,7 +1681,6 @@ view names and view classes that the resolver can use. The following example sho definition for a `ResourceBundleViewResolver` and the corresponding view names and view classes (taken from the Pet Clinic sample): -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1815,7 +1703,6 @@ classes (taken from the Pet Clinic sample): findOwnersForm.url=/WEB-INF/jsp/findOwners.jsp ... ---- -==== When you use the `ResourceBundleViewResolver`, you can easily mix different view technologies. @@ -1845,7 +1732,6 @@ configuration, scoped beans, and so on. Note that you need to define one Spring for each preparer name (as used in your Tiles definitions). The following example shows how to define a set a `SpringBeanPreparerFactory` property on a `TilesConfigurer` bean: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1866,7 +1752,6 @@ how to define a set a `SpringBeanPreparerFactory` property on a `TilesConfigurer ---- -==== @@ -1883,7 +1768,6 @@ package `org.springframework.web.servlet.view.feed`. optionally override the `buildFeedMetadata()` method (the default implementation is empty). The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1903,11 +1787,9 @@ empty). The following example shows how to do so: } ---- -==== Similar requirements apply for implementing `AbstractRssFeedView`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1926,7 +1808,6 @@ Similar requirements apply for implementing `AbstractRssFeedView`, as the follow } } ---- -==== The `buildFeedItems()` and `buildFeedEntries()` methods pass in the HTTP request, in case you need to access the Locale. The HTTP response is passed in only for the setting of @@ -1973,7 +1854,6 @@ A simple PDF view for a word list could extend `org.springframework.web.servlet.view.document.AbstractPdfView` and implement the `buildPdfDocument()` method, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1989,7 +1869,6 @@ A simple PDF view for a word list could extend } } ---- -==== A controller can return such a view either from an external view definition (referencing it by name) or as a `View` instance from the handler method. @@ -2094,7 +1973,6 @@ Configuration is standard for a simple Spring web application: The MVC configura has to define an `XsltViewResolver` bean and regular MVC annotation configuration. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2112,7 +1990,6 @@ public class WebConfig implements WebMvcConfigurer { } } ---- -==== @@ -2124,7 +2001,6 @@ We also need a Controller that encapsulates our word-generation logic. The controller logic is encapsulated in a `@Controller` class, with the handler method being defined as follows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2149,7 +2025,6 @@ handler method being defined as follows: } } ---- -==== So far, we have only created a DOM document and added it to the Model map. Note that you can also load an XML file as a `Resource` and use it instead of a custom DOM document. @@ -2172,7 +2047,6 @@ and end with an `xslt` file extension. The following example shows an XSLT transform: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -2199,11 +2073,9 @@ The following example shows an XSLT transform: ---- -==== The preceding transform is rendered as the following HTML: -==== [source,html,indent=0] [subs="verbatim,quotes"] ---- @@ -2222,4 +2094,3 @@ The preceding transform is rendered as the following HTML: ---- -==== diff --git a/src/docs/asciidoc/web/webmvc.adoc b/src/docs/asciidoc/web/webmvc.adoc index f53375c482..1c8660fe0d 100644 --- a/src/docs/asciidoc/web/webmvc.adoc +++ b/src/docs/asciidoc/web/webmvc.adoc @@ -40,7 +40,6 @@ The following example of the Java configuration registers and initializes the `DispatcherServlet`, which is auto-detected by the Servlet container (see <>): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -62,7 +61,6 @@ the `DispatcherServlet`, which is auto-detected by the Servlet container } } ---- -==== NOTE: In addition to using the ServletContext API directly, you can also extend `AbstractAnnotationConfigDispatcherServletInitializer` and override specific methods @@ -70,7 +68,6 @@ NOTE: In addition to using the ServletContext API directly, you can also extend The following example of `web.xml` configuration registers and initializes the `DispatcherServlet`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -102,7 +99,6 @@ The following example of `web.xml` configuration registers and initializes the ` ---- -==== NOTE: Spring Boot follows a different initialization sequence. Rather than hooking into the lifecycle of the Servlet container, Spring Boot uses Spring configuration to @@ -139,7 +135,6 @@ image::images/mvc-context-hierarchy.png[] The following example configures a `WebApplicationContext` hierarchy: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -161,14 +156,12 @@ The following example configures a `WebApplicationContext` hierarchy: } } ---- -==== TIP: If an application context hierarchy is not required, applications can return all configuration through `getRootConfigClasses()` and `null` from `getServletConfigClasses()`. The following example shows the `web.xml` equivalent: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -200,7 +193,6 @@ The following example shows the `web.xml` equivalent: ---- -==== TIP: If an application context hierarchy is not required, applications may configure a "`root`" context only and leave the `contextConfigLocation` Servlet parameter empty. @@ -293,7 +285,6 @@ In a Servlet 3.0+ environment, you have the option of configuring the Servlet co programmatically as an alternative or in combination with a `web.xml` file. The following example registers a `DispatcherServlet`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -312,7 +303,6 @@ example registers a `DispatcherServlet`: } } ---- -==== `WebApplicationInitializer` is an interface provided by Spring MVC that ensures your implementation is detected and automatically used to initialize any Servlet 3 container. @@ -324,7 +314,6 @@ location of the `DispatcherServlet` configuration. This is recommended for applications that use Java-based Spring configuration, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -346,12 +335,10 @@ following example shows: } } ---- -==== If you use XML-based Spring configuration, you should extend directly from `AbstractDispatcherServletInitializer`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -375,13 +362,11 @@ If you use XML-based Spring configuration, you should extend directly from } } ---- -==== `AbstractDispatcherServletInitializer` also provides a convenient way to add `Filter` instances and have them be automatically mapped to the `DispatcherServlet`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -396,7 +381,6 @@ following example shows: } } ---- -==== Each filter is added with a default name based on its concrete type and automatically mapped to the `DispatcherServlet`. @@ -582,7 +566,6 @@ Servlet containers can render a default error page in HTML. To customize the def error page of the container, you can declare an error page mapping in `web.xml`. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -590,7 +573,6 @@ The following example shows how to do so: /error ---- -==== Given the preceding example, when an exception bubbles up or the response has an error status, the Servlet container makes an ERROR dispatch within the container to the configured URL @@ -598,7 +580,6 @@ Servlet container makes an ERROR dispatch within the container to the configured to a `@Controller`, which could be implemented to return an error view name with a model or to render a JSON response, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -614,7 +595,6 @@ or to render a JSON response, as the following example shows: } } ---- -==== TIP: The Servlet API does not provide a way to create error page mappings in Java. You can, however, use both a `WebApplicationInitializer` and a minimal `web.xml`. @@ -813,7 +793,6 @@ This locale resolver inspects a `Cookie` that might exist on the client to see i properties of this locale resolver, you can specify the name of the cookie as well as the maximum age. The following example defines a `CookieLocaleResolver`: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -826,7 +805,6 @@ maximum age. The following example defines a `CookieLocaleResolver`: ---- -==== The following table describes the properties `CookieLocaleResolver`: @@ -878,7 +856,6 @@ that contain a parameter named `siteLanguage` now changes the locale. So, for ex a request for the URL, `http://www.sf.net/home.view?siteLanguage=nl`, changes the site language to Dutch. The following example shows how to intercept the locale: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -902,7 +879,6 @@ language to Dutch. The following example shows how to intercept the locale: ---- -==== @@ -931,21 +907,18 @@ The web application context automatically detects a bean with that name and uses When you use the `ResourceBundleThemeSource`, a theme is defined in a simple properties file. The properties file lists the resources that make up the theme, as the following example shows: -==== [literal] [subs="verbatim,quotes"] ---- styleSheet=/themes/cool/style.css background=/themes/cool/img/coolBg.jpg ---- -==== The keys of the properties are the names that refer to the themed elements from view code. For a JSP, you typically do this using the `spring:theme` custom tag, which is very similar to the `spring:message` tag. The following JSP fragment uses the theme defined in the previous example to customize the look and feel: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -959,7 +932,6 @@ defined in the previous example to customize the look and feel: ---- -==== By default, the `ResourceBundleThemeSource` uses an empty base name prefix. As a result, the properties files are loaded from the root of the classpath. Thus, you would put the @@ -1037,7 +1009,6 @@ To do so: The following example shows how to set a `MultipartConfigElement` on the Servlet registration: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1054,7 +1025,6 @@ The following example shows how to set a `MultipartConfigElement` on the Servlet } ---- -==== Once the Servlet 3.0 configuration is in place, you can add a bean of type `StandardServletMultipartResolver` with a name of `multipartResolver`. @@ -1087,7 +1057,6 @@ through the `enableLoggingRequestDetails` property on `DispatcherServlet`. The following example shows how to do so by using Java configuration: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1116,7 +1085,6 @@ public class MyInitializer } ---- -==== @@ -1213,7 +1181,6 @@ exception handling, and more. Annotated controllers have flexible method signatu do not have to extend base classes nor implement specific interfaces. The following example shows a controller defined by annotations: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1227,7 +1194,6 @@ The following example shows a controller defined by annotations: } } ---- -==== In the preceding example, the method accepts a `Model` and returns a view name as a `String`, but many other options exist and are explained later in this chapter. @@ -1250,7 +1216,6 @@ annotated class, indicating its role as a web component. To enable auto-detection of such `@Controller` beans, you can add component scanning to your Java configuration, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1261,11 +1226,9 @@ your Java configuration, as the following example shows: // ... } ---- -==== The following example shows the XML configuration equivalent of the preceding example: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -1286,7 +1249,6 @@ The following example shows the XML configuration equivalent of the preceding ex ---- -==== `@RestController` is a <> that is itself meta-annotated with `@Controller` and `@ResponseBody` to indicate a controller whose @@ -1332,7 +1294,6 @@ using `@RequestMapping`, which, by default, matches to all HTTP methods. At the The following example has type and method level mappings: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1352,7 +1313,6 @@ The following example has type and method level mappings: } } ---- -==== [[mvc-ann-requestmapping-uri-templates]] @@ -1368,7 +1328,6 @@ You can map requests by using the following glob patterns and wildcards: You can also declare URI variables and access their values with `@PathVariable`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1377,11 +1336,9 @@ as the following example shows: // ... } ---- -==== You can declare URI variables at the class and method levels, as the following example shows: -==== [source,java,intent=0] [subs="verbatim,quotes"] ---- @@ -1395,7 +1352,6 @@ public class OwnerController { } } ---- -==== URI variables are automatically converted to the appropriate type, or `TypeMismatchException` is raised. Simple types (`int`, `long`, `Date`, and so on) are supported by default and you can @@ -1410,7 +1366,6 @@ The syntax `{varName:regex}` declares a URI variable with a regular expression t syntax of `{varName:regex}`. For example, given URL `"/spring-web-3.0.5 .jar"`, the following method extracts the name, version, and file extension: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1419,7 +1374,6 @@ extracts the name, version, and file extension: // ... } ---- -==== URI path patterns can also have embedded `${...}` placeholders that are resolved on startup by using `PropertyPlaceHolderConfigurer` against local, system, environment, and other property @@ -1519,7 +1473,6 @@ recommendations related to RFD. You can narrow the request mapping based on the `Content-Type` of the request, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1529,7 +1482,7 @@ as the following example shows: } ---- <1> Using a `consumes` attribute to narrow the mapping by the content type. -==== + The `consumes` attribute also supports negation expressions -- for example, `!text/plain` means any content type other than `text/plain`. @@ -1549,7 +1502,6 @@ TIP: `MediaType` provides constants for commonly used media types, such as You can narrow the request mapping based on the `Accept` request header and the list of content types that a controller method produces, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1560,7 +1512,7 @@ content types that a controller method produces, as the following example shows: } ---- <1> Using a `produces` attribute to narrow the mapping by the content type. -==== + The media type can specify a character set. Negated expressions are supported -- for example, `!text/plain` means any content type other than "text/plain". @@ -1586,7 +1538,6 @@ You can narrow request mappings based on request parameter conditions. You can t presence of a request parameter (`myParam`), for the absence of one (`!myParam`), or for a specific value (`myParam=myValue`). The following example shows how to test for a specific value: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1596,11 +1547,10 @@ specific value (`myParam=myValue`). The following example shows how to test for } ---- <1> Testing whether `myParam` equals `myValue`. -==== + You can also use the same with request header conditions, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1610,7 +1560,7 @@ You can also use the same with request header conditions, as the following examp } ---- <1> Testing whether `myHeader` equals `myValue`. -==== + TIP: You can match `Content-Type` and `Accept` with the headers condition, but it is better to use <> and <> @@ -1672,7 +1622,6 @@ You can programmatically register handler methods, which you can use for dynamic registrations or for advanced cases, such as different instances of the same handler under different URLs. The following example registers a handler method: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1698,7 +1647,7 @@ public class MyConfig { <2> Prepare the request mapping meta data. <3> Get the handler method. <4> Add the registration. -==== + @@ -1980,7 +1929,6 @@ method must use a URI variable to mask that variable content and ensure the requ be matched successfully independent of matrix variable order and presence. The following example uses a matrix variable: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1993,13 +1941,11 @@ The following example uses a matrix variable: // q == 11 } ---- -==== Given that all path segments may contain matrix variables, you may sometimes need to disambiguate which path variable the matrix variable is expected to be in. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2014,12 +1960,10 @@ The following example shows how to do so: // q2 == 22 } ---- -==== A matrix variable may be defined as optional and a default value specified, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2031,11 +1975,9 @@ following example shows: // q == 1 } ---- -==== To get all matrix variables, you can use a `MultiValueMap`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2050,7 +1992,6 @@ To get all matrix variables, you can use a `MultiValueMap`, as the following exa // petMatrixVars: ["q" : 22, "s" : 23] } ---- -==== Note that you need to enable the use of matrix variables. In the MVC Java configuration, you need to set a `UrlPathHelper` with `removeSemicolonContent=false` through @@ -2067,7 +2008,6 @@ query parameters or form data) to a method argument in a controller. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2089,7 +2029,7 @@ The following example shows how to do so: } ---- <1> Using `@RequestParam` to bind `petId`. -==== + By default, method parameters that use this annotation are required, but you can specify that a method parameter is optional by setting the `@RequestParam` annotation's `required` flag to @@ -2121,7 +2061,6 @@ controller. Consider the following request, with headers: -==== [literal] [subs="verbatim,quotes"] ---- @@ -2132,11 +2071,9 @@ Accept-Encoding gzip,deflate Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive 300 ---- -==== The following example gets the value of the `Accept-Encoding` and `Keep-Alive` headers: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2149,7 +2086,7 @@ The following example gets the value of the `Accept-Encoding` and `Keep-Alive` h ---- <1> Get the value of the `Accept-Encoding` header. <2> Get the value of the `Keep-Alive` header. -==== + If the target method parameter type is not `String`, type conversion is automatically applied. See <>. @@ -2173,17 +2110,14 @@ in a controller. Consider a request with the following cookie: -==== [literal] [subs="verbatim,quotes"] ---- JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84 ---- -==== The following example shows how to get the cookie value: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2193,7 +2127,7 @@ The following example shows how to get the cookie value: } ---- <1> Get the value of the `JSESSIONID` cookie. -==== + if the target method parameter type is not `String`, type conversion is applied automatically. See <>. @@ -2209,7 +2143,6 @@ values from HTTP Servlet request parameters whose names match to field names. Th referred to as data binding, and it saves you from having to deal with parsing and converting individual query parameters and form fields. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2217,7 +2150,7 @@ converting individual query parameters and form fields. The following example sh public String processSubmit(@ModelAttribute Pet pet) { } <1> ---- <1> Bind an instance of `Pet`. -==== + The `Pet` instance above is resolved as follows: @@ -2235,7 +2168,6 @@ with a URI path variable convention. In the following example, the model attribu `account`, matches the URI path variable, `account`, and the `Account` is loaded by passing the `String` account number through a registered `Converter`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2244,7 +2176,6 @@ the `String` account number through a registered `Converter`: // ... } ---- -==== After the model attribute instance is obtained, data binding is applied. The `WebDataBinder` class matches Servlet request parameter names (query parameters and form @@ -2257,7 +2188,6 @@ Data binding can result in errors. By default, a `BindException` is raised. Howe for such errors in the controller method, you can add a `BindingResult` argument immediately next to the `@ModelAttribute`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2270,13 +2200,12 @@ to the `@ModelAttribute`, as the following example shows: } ---- <1> Adding a `BindingResult` next to the `@ModelAttribute`. -==== + In some cases, you may want access to a model attribute without data binding. For such cases, you can inject the `Model` into the controller and access it directly or, alternatively, set `@ModelAttribute(binding=false)`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2297,14 +2226,13 @@ alternatively, set `@ModelAttribute(binding=false)`, as the following example sh } ---- <1> Setting `@ModelAttribute(binding=false)`. -==== + You can automatically apply validation after data binding by adding the `javax.validation.Valid` annotation or Spring's `@Validated` annotation (ee <> and <>). The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2317,7 +2245,7 @@ You can automatically apply validation after data binding by adding the } ---- <1> Validate the `Pet` instance. -==== + Note that using `@ModelAttribute` is optional (for example, to set its attributes). By default, any argument that is not a simple value type (as determined by @@ -2338,7 +2266,6 @@ requests to access. The following example uses the `@SessionAttributes` annotation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2349,14 +2276,13 @@ The following example uses the `@SessionAttributes` annotation: } ---- <1> Using the `@SessionAttributes` annotation. -==== + On the first request, when a model attribute with the name, `pet`, is added to the model, it is automatically promoted to and saved in the HTTP Servlet session. It remains there until another controller method uses a `SessionStatus` method argument to clear the storage, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2379,7 +2305,7 @@ storage, as the following example shows: ---- <1> Storing the `Pet` value in the Servlet session. <2> Clearing the `Pet` value from the Servlet session. -==== + [[mvc-ann-sessionattribute]] @@ -2391,7 +2317,6 @@ If you need access to pre-existing session attributes that are managed globally you can use the `@SessionAttribute` annotation on a method parameter, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2401,7 +2326,7 @@ as the following example shows: } ---- <1> Using a `@SessionAttribute` annotation. -==== + For use cases that require adding or removing session attributes, consider injecting `org.springframework.web.context.request.WebRequest` or @@ -2420,7 +2345,6 @@ Similar to `@SessionAttribute`, you can use the `@RequestAttribute` annotations access pre-existing request attributes created earlier (for example, by a Servlet `Filter` or `HandlerInterceptor`): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2430,7 +2354,7 @@ or `HandlerInterceptor`): } ---- <1> Using the `@RequestAttribute` annotation. -==== + [[mvc-redirecting-passing-data]] @@ -2461,7 +2385,6 @@ Note that URI template variables from the present request are automatically made available when expanding a redirect URL, and you need explicitly add them through `Model` or `RedirectAttributes`. The following example shows how to define a redirect: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2471,7 +2394,6 @@ through `Model` or `RedirectAttributes`. The following example shows how to defi return "redirect:files/{path}"; } ---- -==== Another way of passing data to the redirect target is by using flash attributes. Unlike other redirect attributes, flash attributes are saved in the HTTP session (and, hence, do @@ -2533,7 +2455,6 @@ requests with `multipart/form-data` is parsed and accessible as regular request parameters. The following example accesses one regular form field and one uploaded file: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2553,7 +2474,6 @@ public class FileUploadController { } } ---- -==== Declaring the argument type as a `List` allows for resolving multiple files for the same parameter name. @@ -2570,7 +2490,6 @@ You can also use multipart content as part of data binding to a and file from the preceding example could be fields on a form object, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2597,12 +2516,10 @@ public class FileUploadController { } } ---- -==== Multipart requests can also be submitted from non-browser clients in a RESTful service scenario. The following example shows a file with JSON: -==== [literal] [subs="verbatim,quotes"] ---- @@ -2638,7 +2555,6 @@ public String handle(**@RequestPart("meta-data") MetaData metadata, // ... } ---- -==== You can use `@RequestPart` in combination with `javax.validation.Valid` or use Spring's `@Validated` annotation, both of which cause Standard Bean Validation to be applied. @@ -2647,7 +2563,6 @@ into a 400 (BAD_REQUEST) response. Alternatively, you can handle validation erro within the controller through an `Errors` or `BindingResult` argument, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2657,7 +2572,6 @@ public String handle(**@Valid** @RequestPart("meta-data") MetaData metadata, // ... } ---- -==== [[mvc-ann-requestbody]] @@ -2668,7 +2582,6 @@ You can use the `@RequestBody` annotation to have the request body read and dese `Object` through an <>. The following example uses a `@RequestBody` argument: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2677,7 +2590,6 @@ The following example uses a `@RequestBody` argument: // ... } ---- -==== You can use the <> option of the <> to configure or customize message conversion. @@ -2689,7 +2601,6 @@ into a 400 (BAD_REQUEST) response. Alternatively, you can handle validation erro within the controller through an `Errors` or `BindingResult` argument, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2698,7 +2609,6 @@ as the following example shows: // ... } ---- -==== [[mvc-ann-httpentity]] @@ -2708,7 +2618,6 @@ as the following example shows: `HttpEntity` is more or less identical to using <> but is based on a container object that exposes request headers and body. The following listing shows an example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2717,7 +2626,6 @@ container object that exposes request headers and body. The following listing sh // ... } ---- -==== [[mvc-ann-responsebody]] @@ -2728,7 +2636,6 @@ You can use the `@ResponseBody` annotation on a method to have the return serial response body through an <>. The following listing shows an example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2738,7 +2645,6 @@ response body through an // ... } ---- -==== `@ResponseBody` is also supported at the class level, in which case it is inherited by all controller methods. This is the effect of `@RestController`, which is nothing more @@ -2760,7 +2666,6 @@ See <> for details. `ResponseEntity` is like <> but with status and headers. For example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2771,7 +2676,6 @@ See <> for details. return ResponseEntity.ok().eTag(etag).build(body); } ---- -==== Spring MVC supports using a single value <> to produce the `ResponseEntity` asynchronously, and/or single and multi-value reactive @@ -2793,7 +2697,6 @@ which allow rendering only a subset of all fields in an `Object`. To use it with `@ResponseBody` or `ResponseEntity` controller methods, you can use Jackson's `@JsonView` annotation to activate a serialization view class, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2834,7 +2737,6 @@ which allow rendering only a subset of all fields in an `Object`. To use it with } } ---- -==== NOTE: `@JsonView` allows an array of view classes, but you can specify only one per controller method. If you need to activate multiple views, you can use a composite interface. @@ -2842,7 +2744,6 @@ controller method. If you need to activate multiple views, you can use a composi For controllers that rely on view resolution, you can add the serialization view class to the model, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2857,7 +2758,6 @@ to the model, as the following example shows: } } ---- -==== @@ -2886,7 +2786,6 @@ related to the request body. The following example shows a `@ModelAttribute` method: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2896,11 +2795,9 @@ The following example shows a `@ModelAttribute` method: // add more ... } ---- -==== The following example adds only one attribute: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2909,7 +2806,6 @@ The following example adds only one attribute: return accountRepository.findAccount(number); } ---- -==== NOTE: When a name is not explicitly specified, a default name is chosen based on the `Object` type, as explained in the javadoc for {api-spring-framework}/core/Conventions.html[`Conventions`]. @@ -2922,7 +2818,6 @@ attribute. This is typically not required, as it is the default behavior in HTML unless the return value is a `String` that would otherwise be interpreted as a view name. `@ModelAttribute` can also customize the model attribute name, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2933,7 +2828,6 @@ unless the return value is a `String` that would otherwise be interpreted as a v return account; } ---- -==== @@ -2959,7 +2853,6 @@ do, except for `@ModelAttribute` (command object) arguments. Typically, they are with a `WebDataBinder` argument (for registrations) and a `void` return value. The following listing shows an example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2977,13 +2870,12 @@ The following listing shows an example: } ---- <1> Defining an `@InitBinder` method. -==== + Alternatively, when you use a `Formatter`-based setup through a shared `FormattingConversionService`, you can re-use the same approach and register controller-specific `Formatter` implementations, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2999,7 +2891,7 @@ controller-specific `Formatter` implementations, as the following example shows: } ---- <1> Defining an `@InitBinder` method on a custom formatter. -==== + @@ -3010,7 +2902,6 @@ controller-specific `Formatter` implementations, as the following example shows: `@Controller` and <> classes can have `@ExceptionHandler` methods to handle exceptions from controller methods, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3025,7 +2916,6 @@ controller-specific `Formatter` implementations, as the following example shows: } } ---- -==== The exception may match against a top-level exception being propagated (that is, a direct `IOException` being thrown) or against the immediate cause within a top-level wrapper exception @@ -3039,7 +2929,6 @@ used to sort exceptions based on their depth from the thrown exception type. Alternatively, the annotation declaration may narrow the exception types to match, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3048,12 +2937,10 @@ as the following example shows: // ... } ---- -==== You can even use a list of specific exception types with a very generic argument signature, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3062,7 +2949,6 @@ as the following example shows: // ... } ---- -==== [NOTE] ==== @@ -3274,7 +3160,6 @@ By default, `@ControllerAdvice` methods apply to every request (that is, all con you can narrow that down to a subset of controllers by using attributes on the annotation, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3290,7 +3175,6 @@ as the following example shows: @ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class}) public class ExampleAdvice3 {} ---- -==== The selectors in the preceding example are evaluated at runtime and may negatively impact performance if used extensively. See the @@ -3316,7 +3200,6 @@ include::web-uris.adoc[leveloffset=+2] You can use `ServletUriComponentsBuilder` to create URIs relative to the current request, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3329,11 +3212,9 @@ as the following example shows: .expand("123") .encode(); ---- -==== You can create URIs relative to the context path, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3342,12 +3223,10 @@ You can create URIs relative to the context path, as the following example shows ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromContextPath(request) .path("/accounts").build() ---- -==== You can create URIs relative to a Servlet (for example, `/main/{asterisk}`), as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3356,7 +3235,6 @@ as the following example shows: ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromServletMapping(request) .path("/accounts").build() ---- -==== NOTE: As of 5.1, `ServletUriComponentsBuilder` ignores information from the `Forwarded` and `X-Forwarded-*` headers, which specify the client-originated address. Consider using the @@ -3371,7 +3249,6 @@ such headers. Spring MVC provides a mechanism to prepare links to controller methods. For example, the following MVC controller allows for link creation: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3385,11 +3262,9 @@ the following MVC controller allows for link creation: } } ---- -==== You can prepare a link by referring to the method by name, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3398,7 +3273,6 @@ You can prepare a link by referring to the method by name, as the following exam URI uri = uriComponents.encode().toUri(); ---- -==== In the preceding example, we provide actual method argument values (in this case, the long value: `21`) to be used as a path variable and inserted into the URL. Furthermore, we provide the @@ -3411,7 +3285,6 @@ There are additional ways to use `MvcUriComponentsBuilder`. For example, you can akin to mock testing through proxies to avoid referring to the controller method by name, as the following example shows (the example assumes static import of `MvcUriComponentsBuilder.on`): -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3420,7 +3293,6 @@ akin to mock testing through proxies to avoid referring to the controller method URI uri = uriComponents.encode().toUri(); ---- -==== NOTE: Controller method signatures are limited in their design when they are supposed to be usable for link creation with `fromMethodCall`. Aside from needing a proper parameter signature, @@ -3442,7 +3314,6 @@ For such cases, you can use the static `fromXxx` overloaded methods that accept with a base URL and then use the instance-based `withXxx` methods. For example, the following listing uses `withMethodCall`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3452,7 +3323,6 @@ following listing uses `withMethodCall`: URI uri = uriComponents.encode().toUri(); ---- -==== NOTE: As of 5.1, `MvcUriComponentsBuilder` ignores information from the `Forwarded` and `X-Forwarded-*` headers, which specify the client-originated address. Consider using the @@ -3469,7 +3339,6 @@ by referring to the implicitly or explicitly assigned name for each request mapp Consider the following example: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3480,11 +3349,9 @@ Consider the following example: public HttpEntity getAddress(@PathVariable String country) { ... } } ---- -==== Given the preceding controller, you can prepare a link from a JSP, as follows: -==== [source,jsp,indent=0] [subs="verbatim,quotes"] ---- @@ -3492,7 +3359,6 @@ Given the preceding controller, you can prepare a link from a JSP, as follows: ... Get Address ---- -==== The preceding example relies on the `mvcUrl` function declared in the Spring tag library (that is, META-INF/spring.tld), but it is easy to define your own function or prepare a @@ -3533,7 +3399,6 @@ Once the asynchronous request processing feature is wrap any supported controller method return value with `DeferredResult`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3548,7 +3413,6 @@ example shows: // From some other thread... deferredResult.setResult(data); ---- -==== The controller can produce the return value asynchronously, from a different thread -- for example, in response to an external event (JMS message), a scheduled task, or other event. @@ -3562,7 +3426,6 @@ example, in response to an external event (JMS message), a scheduled task, or ot A controller can wrap any supported return value with `java.util.concurrent.Callable`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3578,7 +3441,6 @@ as the following example shows: } ---- -==== The return value can then be obtained by running the the given task through the <> `TaskExecutor`. @@ -3711,7 +3573,6 @@ each object is serialized with an <> and written to the response, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3731,7 +3592,6 @@ response, as the following example shows: // and done at some point emitter.complete(); ---- -==== You can also use `ResponseBodyEmitter` as the body in a `ResponseEntity`, letting you customize the status and headers of the response. @@ -3752,7 +3612,6 @@ http://www.w3.org/TR/eventsource/[Server-Sent Events], where events sent from th are formatted according to the W3C SSE specification. To produce an SSE stream from a controller, return `SseEmitter`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3772,7 +3631,6 @@ stream from a controller, return `SseEmitter`, as the following example shows: // and done at some point emitter.complete(); ---- -==== While SSE is the main option for streaming into browsers, note that Internet Explorer does not support Server-Sent Events. Consider using Spring's @@ -3790,7 +3648,6 @@ Sometimes, it is useful to bypass message conversion and stream directly to the `OutputStream` (for example, for a file download). You can use the `StreamingResponseBody` return value type to do so, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3804,7 +3661,6 @@ return value type to do so, as the following example shows: }; } ---- -==== You can use `StreamingResponseBody` as the body in a `ResponseEntity` to customize the status and headers of the response. @@ -3965,7 +3821,6 @@ While https://tools.ietf.org/html/rfc7234#section-5.2.2[RFC 7234] describes all directives for the `Cache-Control` response header, the `CacheControl` type takes a use case-oriented approach that focuses on the common scenarios: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -3980,7 +3835,6 @@ use case-oriented approach that focuses on the common scenarios: // "Cache-Control: max-age=864000, public, no-transform" CacheControl ccCustom = CacheControl.maxAge(10, TimeUnit.DAYS).noTransform().cachePublic(); ---- -==== `WebContentGenerator` also accept a simpler `cachePeriod` property (defined in seconds) that works as follows: @@ -4001,7 +3855,6 @@ Controllers can add explicit support for HTTP caching. We recommended doing so, against conditional request headers. A controller can add an `ETag` header and `Cache-Control` settings to a `ResponseEntity`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4018,7 +3871,6 @@ settings to a `ResponseEntity`, as the following example shows: .body(book); } ---- -==== The preceding example sends an 304 (NOT_MODIFIED) response with an empty body if the comparison to the conditional request headers indicates that the content has not changed. Otherwise, the @@ -4027,7 +3879,6 @@ to the conditional request headers indicates that the content has not changed. O You can also make the check against conditional request headers in the controller, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4048,7 +3899,7 @@ as the following example shows: <1> Application-specific calculation. <2> The response has been set to 304 (NOT_MODIFIED) -- no further processing. <3> Continue with the request processing. -==== + There are three variants for checking conditional requests against `eTag` values, `lastModified` values, or both. For conditional `GET` and `HEAD` requests, you can set the response to @@ -4100,7 +3951,6 @@ and <>. In Java configuration, you can use the `@EnableWebMvc` annotation to enable MVC configuration, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4109,12 +3959,10 @@ configuration, as the following example shows: public class WebConfig { } ---- -==== In XML configuration, you can use the `` element to enable MVC configuration, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4132,7 +3980,6 @@ configuration, as the following example shows: ---- -==== The preceding example registers a number of Spring MVC <> and adapts to dependencies @@ -4147,7 +3994,6 @@ available on the classpath (for example, payload converters for JSON, XML, and o In Java configuration, you can implement the `WebMvcConfigurer` interface, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4158,7 +4004,6 @@ following example shows: // Implement configuration methods... } ---- -==== In XML, you can check attributes and sub-elements of ``. You can view the http://schema.spring.io/mvc/spring-mvc.xsd[Spring MVC XML schema] or use @@ -4178,7 +4023,6 @@ formatting library is also installed if Joda-Time is present on the classpath. In Java configuration, you can register custom formatters and converters, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4192,11 +4036,9 @@ following example shows: } } ---- -==== The following example shows how to achieve the same configuration in XML: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4234,7 +4076,6 @@ The following example shows how to achieve the same configuration in XML: ---- -==== NOTE: See <> and the `FormattingConversionServiceFactoryBean` for more information on when to use FormatterRegistrar implementations. @@ -4253,7 +4094,6 @@ controller method arguments. In Java configuration, you can customize the global `Validator` instance, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4267,11 +4107,9 @@ following example shows: } } ---- -==== The following example shows how to achieve the same configuration in XML: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4289,12 +4127,10 @@ The following example shows how to achieve the same configuration in XML: ---- -==== Note that you can also register `Validator` implementations locally, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4308,7 +4144,6 @@ example shows: } ---- -==== TIP: If you need to have a `LocalValidatorFactoryBean` injected somewhere, create a bean and mark it with `@Primary` in order to avoid conflict with the one declared in the MVC configuration. @@ -4321,7 +4156,6 @@ mark it with `@Primary` in order to avoid conflict with the one declared in the In Java configuration, you can register interceptors to apply to incoming requests, as the following example shows: -==== [source,java,indent=0] [subs="verbatim"] ---- @@ -4337,11 +4171,9 @@ the following example shows: } } ---- -==== The following example shows how to achieve the same configuration in XML: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -4358,7 +4190,6 @@ The following example shows how to achieve the same configuration in XML: ---- -==== @@ -4381,7 +4212,6 @@ more details. In Java configuration, you can customize requested content type resolution, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4396,11 +4226,9 @@ following example shows: } } ---- -==== The following example shows how to achieve the same configuration in XML: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4415,7 +4243,6 @@ The following example shows how to achieve the same configuration in XML:
---- -==== @@ -4432,7 +4259,6 @@ You can customize `HttpMessageConverter` in Java configuration by overriding The following example adds XML and Jackson JSON converters with a customized `ObjectMapper` instead of the default ones: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4451,7 +4277,6 @@ The following example adds XML and Jackson JSON converters with a customized } } ---- -==== In the preceding example, {api-spring-framework}/http/converter/json/Jackson2ObjectMapperBuilder.html[`Jackson2ObjectMapperBuilder`] @@ -4484,7 +4309,6 @@ Other interesting Jackson modules are available: The following example shows how to achieve the same configuration in XML: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4506,7 +4330,6 @@ The following example shows how to achieve the same configuration in XML: ---- -==== @@ -4519,7 +4342,6 @@ logic to execute before the view generates the response. The following example of Java configuration forwards a request for `/` to a view called `home`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4533,18 +4355,15 @@ The following example of Java configuration forwards a request for `/` to a view } } ---- -==== The following example achieves the same thing as the preceding example, but with XML, by using the `` element: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== @@ -4557,7 +4376,6 @@ The MVC configuration simplifies the registration of view resolvers. The following Java configuration example configures content negotiation view resolution by using JSP and Jackson as a default `View` for JSON rendering: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4572,11 +4390,9 @@ resolution by using JSP and Jackson as a default `View` for JSON rendering: } } ---- -==== The following example shows how to achieve the same configuration in XML: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4589,14 +4405,12 @@ The following example shows how to achieve the same configuration in XML: ---- -==== Note, however, that FreeMarker, Tiles, Groovy Markup, and script templates also require configuration of the underlying view technology. The MVC namespace provides dedicated elements. The following example works with FreeMarker: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4615,12 +4429,10 @@ The MVC namespace provides dedicated elements. The following example works with ---- -==== In Java configuration, you can add the respective `Configurer` bean, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4642,7 +4454,6 @@ as the following example shows: } } ---- -==== @@ -4662,7 +4473,6 @@ status code is returned. The following listing shows how to do so with Java configuration: -==== [source,java,indent=0] [subs="verbatim"] ---- @@ -4678,11 +4488,9 @@ The following listing shows how to do so with Java configuration: } } ---- -==== The following example shows how to achieve the same configuration in XML: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4690,7 +4498,6 @@ The following example shows how to achieve the same configuration in XML: location="/public, classpath:/static/" cache-period="31556926" /> ---- -==== See also <>. @@ -4707,7 +4514,6 @@ JavaScript resources used with a module loader. The following example shows how to use `VersionResourceResolver` in Java configuration: -==== [source,java,indent=0] [subs="verbatim"] ---- @@ -4724,11 +4530,9 @@ The following example shows how to use `VersionResourceResolver` in Java configu } } ---- -==== The following example shows how to achieve the same configuration in XML: -==== [source,xml,indent=0] [subs="verbatim"] ---- @@ -4743,7 +4547,6 @@ The following example shows how to achieve the same configuration in XML: ---- -==== You can then use `ResourceUrlProvider` to rewrite URLs and apply the full chain of resolvers and transformers -- for example, to insert versions. The MVC configuration provides a `ResourceUrlProvider` @@ -4780,7 +4583,6 @@ lower than that of the `DefaultServletHttpRequestHandler`, which is `Integer.MAX The following example shows how to enable the feature by using the default setup: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4794,17 +4596,14 @@ The following example shows how to enable the feature by using the default setup } } ---- -==== The following example shows how to achieve the same configuration in XML: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== The caveat to overriding the `/` Servlet mapping is that the `RequestDispatcher` for the default Servlet must be retrieved by name rather than by path. The @@ -4815,7 +4614,6 @@ If the default Servlet has been custom-configured with a different name, or if a different Servlet container is being used where the default Servlet name is unknown, then you must explicitly provide the default Servlet's name, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4830,17 +4628,14 @@ then you must explicitly provide the default Servlet's name, as the following ex } ---- -==== The following example shows how to achieve the same configuration in XML: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- ---- -==== @@ -4854,7 +4649,6 @@ For details on the individual options, see the The following example shows how to customize path matching in Java configuration: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4886,11 +4680,9 @@ The following example shows how to customize path matching in Java configuration } ---- -==== The following example shows how to achieve the same configuration in XML: -==== [source,xml,indent=0] [subs="verbatim,quotes"] ---- @@ -4906,7 +4698,6 @@ The following example shows how to achieve the same configuration in XML: ---- -==== @@ -4923,7 +4714,6 @@ For advanced mode, you can remove `@EnableWebMvc` and extend directly from `DelegatingWebMvcConfiguration` instead of implementing `WebMvcConfigurer`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4934,7 +4724,6 @@ as the following example shows: } ---- -==== You can keep existing methods in `WebConfig`, but you can now also override bean declarations from the base class, and you can still have any number of other `WebMvcConfigurer` implementations on @@ -4949,7 +4738,6 @@ The MVC namespace does not have an advanced mode. If you need to customize a pro a bean that you cannot change otherwise, you can use the `BeanPostProcessor` lifecycle hook of the Spring `ApplicationContext`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -4961,7 +4749,6 @@ hook of the Spring `ApplicationContext`, as the following example shows: } } ---- -==== Note that you need to declare `MyPostProcessor` as a bean, either explicitly in XML or by letting it be detected through a `` declaration. diff --git a/src/docs/asciidoc/web/websocket-intro.adoc b/src/docs/asciidoc/web/websocket-intro.adoc index 29fe911700..61761e2beb 100644 --- a/src/docs/asciidoc/web/websocket-intro.adoc +++ b/src/docs/asciidoc/web/websocket-intro.adoc @@ -10,7 +10,6 @@ A WebSocket interaction begins with an HTTP request that uses the HTTP `Upgrade` to upgrade or, in this case, to switch to the WebSocket protocol. The following example shows such an interaction: -==== [source,yaml,indent=0] [subs="verbatim,quotes"] ---- @@ -25,12 +24,11 @@ shows such an interaction: ---- <1> The `Upgrade` header. <2> Using the `Upgrade` connection. -==== + Instead of the usual 200 status code, a server with WebSocket support returns output similar to the following: -==== [source,yaml,indent=0] [subs="verbatim,quotes"] ---- @@ -41,7 +39,7 @@ similar to the following: Sec-WebSocket-Protocol: v10.stomp ---- <1> Protocol switch -==== + After a successful handshake, the TCP socket underlying the HTTP upgrade request remains open for both the client and the server to continue to send and receive messages. diff --git a/src/docs/asciidoc/web/websocket.adoc b/src/docs/asciidoc/web/websocket.adoc index e9ca3c68a0..e1976098d9 100644 --- a/src/docs/asciidoc/web/websocket.adoc +++ b/src/docs/asciidoc/web/websocket.adoc @@ -29,7 +29,6 @@ Creating a WebSocket server is as simple as implementing `WebSocketHandler` or, likely, extending either `TextWebSocketHandler` or `BinaryWebSocketHandler`. The following example uses `TextWebSocketHandler`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -46,12 +45,10 @@ example uses `TextWebSocketHandler`: } ---- -==== There is dedicated WebSocket Java configuration and XML namespace support for mapping the preceding WebSocket handler to a specific URL, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -75,11 +72,9 @@ WebSocket handler to a specific URL, as the following example shows: } ---- -==== The following example shows the XML configuration equivalent of the preceding example: -==== [source,xml,indent=0] [subs="verbatim,quotes,attributes"] ---- @@ -100,7 +95,6 @@ The following example shows the XML configuration equivalent of the preceding ex ---- -==== The preceding example is for use in Spring MVC applications and should be included in the configuration of a <>. However, Spring's WebSocket @@ -126,7 +120,6 @@ You can use such an interceptor to preclude the handshake or to make any attribu available to the `WebSocketSession`. The following example uses a built-in interceptor to pass HTTP session attributes to the WebSocket session: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -142,11 +135,9 @@ to pass HTTP session attributes to the WebSocket session: } ---- -==== The following example shows the XML configuration equivalent of the preceding example: -==== [source,xml,indent=0] [subs="verbatim,quotes,attributes"] ---- @@ -170,7 +161,6 @@ The following example shows the XML configuration equivalent of the preceding ex ---- -==== A more advanced option is to extend the `DefaultHandshakeHandler` that performs the steps of the WebSocket handshake, including validating the client origin, @@ -228,7 +218,6 @@ upgrade to a Servlet container version with JSR-356 support, it should be possible to selectively enable or disable web fragments (and SCI scanning) through the use of the `` element in `web.xml`, as the following example shows: -==== [source,xml,indent=0] [subs="verbatim,quotes,attributes"] ---- @@ -243,13 +232,11 @@ through the use of the `` element in `web.xml`, as the foll ---- -==== You can then selectively enable web fragments by name, such as Spring's own `SpringServletContainerInitializer` that provides support for the Servlet 3 Java initialization API. The following example shows how to do so: -==== [source,xml,indent=0] [subs="verbatim,quotes,attributes"] ---- @@ -266,7 +253,6 @@ Java initialization API. The following example shows how to do so: ---- -==== @@ -281,7 +267,6 @@ and others. For Tomcat, WildFly, and GlassFish, you can add a `ServletServerContainerFactoryBean` to your WebSocket Java config, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -299,11 +284,9 @@ WebSocket Java config, as the following example shows: } ---- -==== The following example shows the XML configuration equivalent of the preceding example: -==== [source,xml,indent=0] [subs="verbatim,quotes,attributes"] ---- @@ -323,7 +306,6 @@ The following example shows the XML configuration equivalent of the preceding ex ---- -==== NOTE: For client-side WebSocket configuration, you should use `WebSocketContainerFactoryBean` (XML) or `ContainerProvider.getWebSocketContainer()` (Java configuration). @@ -332,7 +314,6 @@ For Jetty, you need to supply a pre-configured Jetty `WebSocketServerFactory` an that into Spring's `DefaultHandshakeHandler` through your WebSocket Java config. The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -359,11 +340,9 @@ The following example shows how to do so: } ---- -==== The following example shows the XML configuration equivalent of the preceding example: -==== [source,xml,indent=0] [subs="verbatim,quotes,attributes"] ---- @@ -401,7 +380,6 @@ The following example shows the XML configuration equivalent of the preceding ex ---- -==== @@ -430,7 +408,6 @@ The three possible behaviors are: You can configure WebSocket and SockJS allowed origins, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -454,11 +431,9 @@ You can configure WebSocket and SockJS allowed origins, as the following example } ---- -==== The following example shows the XML configuration equivalent of the preceding example: -==== [source,xml,indent=0] [subs="verbatim,quotes,attributes"] ---- @@ -479,7 +454,6 @@ The following example shows the XML configuration equivalent of the preceding ex ---- -==== @@ -532,7 +506,6 @@ polling is used. All transport requests have the following URL structure: -==== ---- http://host:port/myApp/myEndpoint/{server-id}/{session-id}/{transport} ---- @@ -542,7 +515,6 @@ where: * `{server-id}` is useful for routing requests in a cluster but is not used otherwise. * `{session-id}` correlates HTTP requests belonging to a SockJS session. * `{transport}` indicates the transport type (for example, `websocket`, `xhr-streaming`, and others). -==== The WebSocket transport needs only a single HTTP request to do the WebSocket handshake. All messages thereafter are exchanged on that socket. @@ -572,7 +544,6 @@ http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html[narrated test You can enable SockJS through Java configuration, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -592,11 +563,9 @@ You can enable SockJS through Java configuration, as the following example shows } ---- -==== The following example shows the XML configuration equivalent of the preceding example: -==== [source,xml,indent=0] [subs="verbatim,quotes,attributes"] ---- @@ -618,7 +587,6 @@ The following example shows the XML configuration equivalent of the preceding ex ---- -==== The preceding example is for use in Spring MVC applications and should be included in the configuration of a <>. However, Spring's WebSocket @@ -690,7 +658,6 @@ a URL from the same origin as the application. The following example shows how to do so in Java configuration: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -708,7 +675,6 @@ The following example shows how to do so in Java configuration: } ---- -==== The XML namespace provides a similar option through the `` element. @@ -821,7 +787,6 @@ to the server. At present there are two implementations: The following example shows how to create a SockJS client and connect to a SockJS endpoint: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -832,7 +797,6 @@ The following example shows how to create a SockJS client and connect to a SockJ SockJsClient sockJsClient = new SockJsClient(transports); sockJsClient.doHandshake(new MyWebSocketHandler(), "ws://example.com:8080/sockjs"); ---- -==== NOTE: SockJS uses JSON formatted arrays for messages. By default, Jackson 2 is used and needs to be on the classpath. Alternatively, you can configure a custom implementation of @@ -842,7 +806,6 @@ To use `SockJsClient` to simulate a large number of concurrent users, you need to configure the underlying HTTP client (for XHR transports) to allow a sufficient number of connections and threads. The following example shows how to do so with Jetty: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -850,12 +813,10 @@ HttpClient jettyHttpClient = new HttpClient(); jettyHttpClient.setMaxConnectionsPerDestination(1000); jettyHttpClient.setExecutor(new QueuedThreadPool(1000)); ---- -==== The following example shows the server-side SockJS-related properties (see javadoc for details) that you should also consider customizing: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -877,7 +838,6 @@ that you should also consider customizing: <2> Set the `httpMessageCacheSize` property to 1,000 (the default is `100`). <3> Set the `disconnectDelay` property to 30 property seconds (the default is five seconds -- `5 * 1000`). -==== @@ -908,7 +868,6 @@ either text or binary. STOMP is a frame-based protocol whose frames are modeled on HTTP. The following listing shows the structure of a STOMP frame: -==== ---- COMMAND header1:value1 @@ -916,7 +875,6 @@ header2:value2 Body^@ ---- -==== Clients can use the `SEND` or `SUBSCRIBE` commands to send or subscribe for messages, along with a `destination` header that describes what the @@ -940,7 +898,6 @@ The following example shows a client subscribing to receive stock quotes, which the server may emit periodically (for example, via a scheduled task that sends messages through a `SimpMessagingTemplate` to the broker): -==== ---- SUBSCRIBE id:sub-1 @@ -948,12 +905,10 @@ destination:/topic/price.stock.* ^@ ---- -==== The following example shows a client that sends a trade request, which the server can handle through an `@MessageMapping` method: -==== ---- SEND destination:/queue/trade @@ -962,7 +917,6 @@ content-length:44 {"action":"BUY","ticker":"MMM","shares",44}^@ ---- -==== After the execution, the server can broadcast a trade confirmation message and details down to the client. @@ -977,7 +931,6 @@ exchanges. STOMP servers can use the `MESSAGE` command to broadcast messages to all subscribers. The following example shows a server sending a stock quote to a subscribed client: -==== ---- MESSAGE message-id:nxahklf6-1 @@ -986,7 +939,6 @@ destination:/topic/price.stock.MMM {"ticker":"MMM","price":129.45}^@ ---- -==== A server cannot send unsolicited messages. All messages from a server must be in response to a specific client subscription, and the @@ -1026,7 +978,6 @@ STOMP over WebSocket support is available in the `spring-messaging` and `spring-websocket` modules. Once you have those dependencies, you can expose a STOMP endpoints, over WebSocket with <>, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1056,11 +1007,10 @@ client needs to connect for the WebSocket handshake. `@MessageMapping` methods in `@Controller` classes. <3> Use the built-in message broker for subscriptions and broadcasting and route messages whose destination header begins with `/topic `or `/queue` to the broker. -==== + The following example shows the XML configuration equivalent of the preceding example: -==== [source,xml,indent=0] [subs="verbatim,quotes,attributes"] ---- @@ -1082,7 +1032,6 @@ The following example shows the XML configuration equivalent of the preceding ex ---- -==== NOTE: For the built-in simple broker, the `/topic` and `/queue` prefixes do not have any special meaning. They are merely a convention to differentiate between pub-sub versus point-to-point @@ -1099,7 +1048,6 @@ https://github.com/JSteunou/webstomp-client[JSteunou/webstomp-client] is the mos actively maintained and evolving successor of that library. The following example code is based on it: -==== [source,javascript,indent=0] [subs="verbatim,quotes"] ---- @@ -1109,11 +1057,9 @@ is based on it: stompClient.connect({}, function(frame) { } ---- -==== Alternatively, if you connect through WebSocket (without SockJS), you can use the following code: -==== [source,javascript,indent=0] [subs="verbatim,quotes"] ---- @@ -1123,7 +1069,6 @@ Alternatively, if you connect through WebSocket (without SockJS), you can use th stompClient.connect({}, function(frame) { } ---- -==== Note that `stompClient` in the preceding example does not need to specify `login` and `passcode` headers. Even if it did, they would be ignored (or, rather, overridden) on the server side. See @@ -1146,7 +1091,6 @@ To configure the underlying WebSocket server, the information in <> applies. For Jetty, however you need to set the `HandshakeHandler` and `WebSocketPolicy` through the `StompEndpointRegistry`: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1171,7 +1115,6 @@ the `HandshakeHandler` and `WebSocketPolicy` through the `StompEndpointRegistry` } } ---- -==== @@ -1237,7 +1180,6 @@ to broadcast to subscribed clients. We can trace the flow through a simple example. Consider the following example, which sets up a server: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1269,7 +1211,6 @@ We can trace the flow through a simple example. Consider the following example, } ---- -==== The preceding example supports the following flow: @@ -1419,7 +1360,6 @@ when a subscription is stored and ready for broadcasts, a client should ask for receipt if the server supports it (simple broker does not). For example, with the Java <>, you could do the following to add a receipt: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1438,7 +1378,6 @@ receipt if the server supports it (simple broker does not). For example, with th // Subscription ready... }); ---- -==== A server side option is <> an `ExecutorChannelInterceptor` on the `brokerChannel` and implement the `afterMessageHandled` @@ -1453,7 +1392,6 @@ An application can use `@MessageExceptionHandler` methods to handle exceptions f itself or through a method argument if you want to get access to the exception instance. The following example declares an exception through a method argument: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1469,7 +1407,6 @@ The following example declares an exception through a method argument: } } ---- -==== `@MessageExceptionHandler` methods support flexible method signatures and support the same method argument types and return values as <> methods. @@ -1490,7 +1427,6 @@ The easiest way to do so is to inject a `SimpMessagingTemplate` and use it to send messages. Typically, you would inject it by type, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1512,7 +1448,6 @@ type, as the following example shows: } ---- -==== However, you can also qualify it by its name (`brokerMessagingTemplate`), if another bean of the same type exists. @@ -1535,7 +1470,6 @@ https://stomp.github.io/stomp-specification-1.2.html#Heart-beating[STOMP heartbe For that, you can declare your own scheduler or use the one that is automatically declared and used internally. The following example shows how to declare your own scheduler: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1561,7 +1495,6 @@ public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { } } ---- -==== @@ -1582,7 +1515,6 @@ and run it with STOMP support enabled. Then you can enable the STOMP broker rela The following example configuration enables a full-featured broker: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1603,11 +1535,9 @@ The following example configuration enables a full-featured broker: } ---- -==== The following example shows the XML configuration equivalent of the preceding example: -==== [source,xml,indent=0] [subs="verbatim,quotes,attributes"] ---- @@ -1629,7 +1559,6 @@ The following example shows the XML configuration equivalent of the preceding ex ---- -==== The STOMP broker relay in the preceding configuration is a Spring {api-spring-framework}/messaging/MessageHandler.html[`MessageHandler`] @@ -1688,7 +1617,6 @@ connectivity is lost, to the same host and port. If you wish to supply multiple on each attempt to connect, you can configure a supplier of addresses, instead of a fixed host and port. The following example shows how to do that: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1711,7 +1639,6 @@ public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { } } ---- -==== You can also configure the STOMP broker relay with a `virtualHost` property. The value of this property is set as the `host` header of every `CONNECT` frame @@ -1731,7 +1658,6 @@ you are more used to messaging conventions, you can switch to using dot (`.`) as The following example shows how to do so in Java configuration: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1749,11 +1675,9 @@ The following example shows how to do so in Java configuration: } } ---- -==== The following example shows the XML configuration equivalent of the preceding example: -==== [source,xml,indent=0] [subs="verbatim,quotes,attributes"] ---- @@ -1779,12 +1703,10 @@ The following example shows the XML configuration equivalent of the preceding ex ---- -==== After that, a controller can use a dot (`.`) as the separator in `@MessageMapping` methods, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1798,7 +1720,6 @@ as the following example shows: } } ---- -==== The client can now send a message to `/app/red.blue.green123`. @@ -1896,7 +1817,6 @@ the user header on the CONNECT `Message`. Spring notes and saves the authenticat user and associate it with subsequent STOMP messages on the same session. The following example shows how register a custom authentication interceptor: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1921,7 +1841,6 @@ example shows how register a custom authentication interceptor: } } ---- -==== Also, note that, when you use Spring Security's authorization for messages, at present, you need to ensure that the authentication `ChannelInterceptor` config is ordered @@ -1956,7 +1875,6 @@ A message-handling method can send messages to the user associated with the message being handled through the `@SendToUser` annotation (also supported on the class-level to share a common destination), as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1971,14 +1889,12 @@ the class-level to share a common destination), as the following example shows: } } ---- -==== If the user has more than one session, by default, all of the sessions subscribed to the given destination are targeted. However, sometimes, it may be necessary to target only the session that sent the message being handled. You can do so by setting the `broadcast` attribute to false, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -1998,7 +1914,6 @@ setting the `broadcast` attribute to false, as the following example shows: } } ---- -==== NOTE: While user destinations generally imply an authenticated user, it is not strictly required. A WebSocket session that is not associated with an authenticated user @@ -2011,7 +1926,6 @@ component by, for example, injecting the `SimpMessagingTemplate` created by the the XML namespace. (The bean name is `"brokerMessagingTemplate"` if required for qualification with `@Qualifier`.) The following example shows how to do so: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2033,7 +1947,6 @@ public class TradeServiceImpl implements TradeService { } } ---- -==== NOTE: When you use user destinations with an external message broker, you should check the broker documentation on how to manage inactive queues, so that, when the user session is @@ -2063,7 +1976,6 @@ not match the exact order of publication. If this is an issue, enable the `setPreservePublishOrder` flag, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2079,11 +1991,9 @@ If this is an issue, enable the `setPreservePublishOrder` flag, as the following } ---- -==== The following example shows the XML configuration equivalent of the preceding example: -==== [source,xml,indent=0] [subs="verbatim,quotes,attributes"] ---- @@ -2102,7 +2012,6 @@ The following example shows the XML configuration equivalent of the preceding ex ---- -==== When the flag is set, messages within the same client session are published to the `clientOutboundChannel` one at a time, so that the order of publication is guaranteed. @@ -2158,7 +2067,6 @@ of a STOMP connection but not for every client message. Applications can also re `ChannelInterceptor` to intercept any message and in any part of the processing chain. The following example shows how to intercept inbound messages from clients: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2172,12 +2080,10 @@ The following example shows how to intercept inbound messages from clients: } } ---- -==== A custom `ChannelInterceptor` can use `StompHeaderAccessor` or `SimpMessageHeaderAccessor` to access information about the message, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2192,7 +2098,6 @@ to access information about the message, as the following example shows: } } ---- -==== Applications can also implement `ExecutorChannelInterceptor`, which is a sub-interface of `ChannelInterceptor` with callbacks in the thread in which the messages are handled. @@ -2215,7 +2120,6 @@ Spring provides a STOMP over WebSocket client and a STOMP over TCP client. To begin, you can create and configure `WebSocketStompClient`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2224,7 +2128,6 @@ To begin, you can create and configure `WebSocketStompClient`, as the following stompClient.setMessageConverter(new StringMessageConverter()); stompClient.setTaskScheduler(taskScheduler); // for heartbeats ---- -==== In the preceding example, you could replace `StandardWebSocketClient` with `SockJsClient`, since that is also an implementation of `WebSocketClient`. The `SockJsClient` can @@ -2233,7 +2136,6 @@ use WebSocket or HTTP-based transport as a fallback. For more details, see Next, you can establish a connection and provide a handler for the STOMP session, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2241,11 +2143,9 @@ Next, you can establish a connection and provide a handler for the STOMP session StompSessionHandler sessionHandler = new MyStompSessionHandler(); stompClient.connect(url, sessionHandler); ---- -==== When the session is ready for use, the handler is notified, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2257,25 +2157,21 @@ public class MyStompSessionHandler extends StompSessionHandlerAdapter { } } ---- -==== Once the session is established, any payload can be sent and is serialized with the configured `MessageConverter`, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- session.send("/topic/something", "payload"); ---- -==== You can also subscribe to destinations. The `subscribe` methods require a handler for messages on the subscription and returns a `Subscription` handle that you can use to unsubscribe. For each received message, the handler can specify the target `Object` type to which the payload should be deserialized, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2293,7 +2189,6 @@ session.subscribe("/topic/something", new StompFrameHandler() { }); ---- -==== To enable STOMP heartbeat, you can configure `WebSocketStompClient` with a `TaskScheduler` and optionally customize the heartbeat intervals (10 seconds for write inactivity, @@ -2329,7 +2224,6 @@ transport-level errors including `ConnectionLostException`. Each WebSocket session has a map of attributes. The map is attached as a header to inbound client messages and may be accessed from a controller method, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2343,7 +2237,6 @@ public class MyController { } } ---- -==== You can declare a Spring-managed bean in the `websocket` scope. You can inject WebSocket-scoped beans into controllers and any channel interceptors @@ -2351,7 +2244,6 @@ registered on the `clientInboundChannel`. Those are typically singletons and liv longer than any individual WebSocket session. Therefore, you need to use a scope proxy mode for WebSocket-scoped beans, as the following example shows: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2388,7 +2280,6 @@ scope proxy mode for WebSocket-scoped beans, as the following example shows: } } ---- -==== As with any custom scope, Spring initializes a new `MyBean` instance the first time it is accessed from the controller and stores the instance in the WebSocket @@ -2462,7 +2353,6 @@ documentation of the XML schema for important additional details. The following example shows a possible configuration: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2479,11 +2369,9 @@ The following example shows a possible configuration: } ---- -==== The following example shows the XML configuration equivalent of the preceding example: -==== [source,xml,indent=0] [subs="verbatim,quotes,attributes"] ---- @@ -2503,7 +2391,6 @@ The following example shows the XML configuration equivalent of the preceding ex ---- -==== You can also use the WebSocket transport configuration shown earlier to configure the maximum allowed size for incoming STOMP messages. In theory, a WebSocket @@ -2521,7 +2408,6 @@ minimum. The following example shows one possible configuration: -==== [source,java,indent=0] [subs="verbatim,quotes"] ---- @@ -2538,11 +2424,9 @@ The following example shows one possible configuration: } ---- -==== The following example shows the XML configuration equivalent of the preceding example: -==== [source,xml,indent=0] [subs="verbatim,quotes,attributes"] ---- @@ -2562,7 +2446,6 @@ The following example shows the XML configuration equivalent of the preceding ex ---- -==== An important point about scaling involves using multiple application instances. Currently, you cannot do that with the simple broker.