Browse Source

Merge branch '5.1.x'

pull/22513/head
Juergen Hoeller 7 years ago
parent
commit
b2b0df893a
  1. 14
      spring-aop/src/main/java/org/aopalliance/intercept/Interceptor.java
  2. 11
      spring-aop/src/test/java/org/springframework/aop/config/TopLevelAopTagTests.java
  3. 11
      spring-aop/src/test/java/org/springframework/aop/framework/PrototypeTargetTests.java
  4. 10
      spring-aop/src/test/java/org/springframework/aop/interceptor/ExposeInvocationInterceptorTests.java
  5. 17
      spring-aop/src/test/java/org/springframework/aop/scope/ScopedProxyAutowireTests.java
  6. 5
      spring-aop/src/test/java/org/springframework/aop/support/RegexpMethodPointcutAdvisorIntegrationTests.java
  7. 41
      spring-aop/src/test/java/org/springframework/aop/target/HotSwappableTargetSourceTests.java
  8. 17
      spring-aop/src/test/java/org/springframework/aop/target/PrototypeTargetSourceTests.java
  9. 16
      spring-aop/src/test/java/org/springframework/aop/target/ThreadLocalTargetSourceTests.java
  10. 31
      spring-beans/src/test/java/org/springframework/beans/factory/ConcurrentBeanFactoryTests.java
  11. 11
      spring-beans/src/test/java/org/springframework/beans/factory/annotation/CustomAutowireConfigurerTests.java
  12. 10
      spring-beans/src/test/java/org/springframework/beans/factory/config/FieldRetrievingFactoryBeanTests.java
  13. 21
      spring-beans/src/test/java/org/springframework/beans/factory/config/ObjectFactoryCreatingFactoryBeanTests.java
  14. 13
      spring-beans/src/test/java/org/springframework/beans/factory/config/SimpleScopeTests.java
  15. 10
      spring-beans/src/test/java/org/springframework/beans/factory/parsing/CustomProblemReporterTests.java
  16. 6
      spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Decoder.java
  17. 4
      spring-web/src/main/java/org/springframework/http/codec/json/Jackson2CodecSupport.java
  18. 77
      spring-web/src/main/java/org/springframework/http/codec/json/Jackson2Tokenizer.java
  19. 11
      spring-web/src/main/java/org/springframework/web/context/support/GenericWebApplicationContext.java
  20. 30
      spring-web/src/test/java/org/springframework/http/codec/json/Jackson2JsonDecoderTests.java
  21. 23
      spring-web/src/test/java/org/springframework/http/codec/json/Jackson2TokenizerTests.java
  22. 16
      src/docs/asciidoc/core.adoc
  23. 26
      src/docs/asciidoc/core/core-aop-api.adoc
  24. 448
      src/docs/asciidoc/core/core-aop.adoc
  25. 149
      src/docs/asciidoc/core/core-appendix.adoc
  26. 138
      src/docs/asciidoc/core/core-beans.adoc
  27. 7
      src/docs/asciidoc/core/core-databuffer-codec.adoc
  28. 31
      src/docs/asciidoc/core/core-expressions.adoc
  29. 64
      src/docs/asciidoc/core/core-null-safety.adoc
  30. 8
      src/docs/asciidoc/core/core-resources.adoc
  31. 88
      src/docs/asciidoc/core/core-validation.adoc
  32. 6
      src/docs/asciidoc/data-access-appendix.adoc
  33. 167
      src/docs/asciidoc/data-access.adoc
  34. 20
      src/docs/asciidoc/index.adoc
  35. 8
      src/docs/asciidoc/integration-appendix.adoc
  36. 797
      src/docs/asciidoc/integration.adoc
  37. 276
      src/docs/asciidoc/languages/dynamic-languages.adoc
  38. 2
      src/docs/asciidoc/languages/groovy.adoc
  39. 157
      src/docs/asciidoc/languages/kotlin.adoc
  40. 6
      src/docs/asciidoc/overview.adoc
  41. 27
      src/docs/asciidoc/testing-webtestclient.adoc
  42. 211
      src/docs/asciidoc/testing.adoc
  43. 27
      src/docs/asciidoc/web-reactive.adoc
  44. 6
      src/docs/asciidoc/web.adoc
  45. 89
      src/docs/asciidoc/web/integration.adoc
  46. 8
      src/docs/asciidoc/web/web-uris.adoc
  47. 14
      src/docs/asciidoc/web/webflux-cors.adoc
  48. 19
      src/docs/asciidoc/web/webflux-functional.adoc
  49. 34
      src/docs/asciidoc/web/webflux-view.adoc
  50. 4
      src/docs/asciidoc/web/webflux-webclient.adoc
  51. 16
      src/docs/asciidoc/web/webflux-websocket.adoc
  52. 311
      src/docs/asciidoc/web/webflux.adoc
  53. 6
      src/docs/asciidoc/web/webmvc-client.adoc
  54. 18
      src/docs/asciidoc/web/webmvc-cors.adoc
  55. 28
      src/docs/asciidoc/web/webmvc-test.adoc
  56. 44
      src/docs/asciidoc/web/webmvc-view.adoc
  57. 338
      src/docs/asciidoc/web/webmvc.adoc
  58. 75
      src/docs/asciidoc/web/websocket.adoc

14
spring-aop/src/main/java/org/aopalliance/intercept/Interceptor.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -33,7 +33,7 @@ import org.aopalliance.aop.Advice; @@ -33,7 +33,7 @@ import org.aopalliance.aop.Advice;
*
* <pre class=code>
* class DebuggingInterceptor implements MethodInterceptor,
* ConstructorInterceptor, FieldInterceptor {
* ConstructorInterceptor {
*
* Object invoke(MethodInvocation i) throws Throwable {
* debug(i.getMethod(), i.getThis(), i.getArgs());
@ -45,16 +45,6 @@ import org.aopalliance.aop.Advice; @@ -45,16 +45,6 @@ import org.aopalliance.aop.Advice;
* return i.proceed();
* }
*
* Object get(FieldAccess fa) throws Throwable {
* debug(fa.getField(), fa.getThis(), null);
* return fa.proceed();
* }
*
* Object set(FieldAccess fa) throws Throwable {
* debug(fa.getField(), fa.getThis(), fa.getValueToSet());
* return fa.proceed();
* }
*
* void debug(AccessibleObject ao, Object this, Object value) {
* ...
* }

11
spring-aop/src/test/java/org/springframework/aop/config/TopLevelAopTagTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,7 +20,6 @@ import org.junit.Test; @@ -20,7 +20,6 @@ import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.Resource;
import static org.junit.Assert.*;
import static org.springframework.tests.TestResourceUtils.*;
@ -33,13 +32,11 @@ import static org.springframework.tests.TestResourceUtils.*; @@ -33,13 +32,11 @@ import static org.springframework.tests.TestResourceUtils.*;
*/
public class TopLevelAopTagTests {
private static final Resource CONTEXT = qualifiedResource(TopLevelAopTagTests.class, "context.xml");
@Test
public void testParse() throws Exception {
public void testParse() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions(CONTEXT);
new XmlBeanDefinitionReader(beanFactory).loadBeanDefinitions(
qualifiedResource(TopLevelAopTagTests.class, "context.xml"));
assertTrue(beanFactory.containsBeanDefinition("testPointcut"));
}

11
spring-aop/src/test/java/org/springframework/aop/framework/PrototypeTargetTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -36,6 +36,7 @@ public class PrototypeTargetTests { @@ -36,6 +36,7 @@ public class PrototypeTargetTests {
private static final Resource CONTEXT = qualifiedResource(PrototypeTargetTests.class, "context.xml");
@Test
public void testPrototypeProxyWithPrototypeTarget() {
TestBeanImpl.constructionCount = 0;
@ -64,12 +65,15 @@ public class PrototypeTargetTests { @@ -64,12 +65,15 @@ public class PrototypeTargetTests {
assertEquals(10, interceptor.invocationCount);
}
public static interface TestBean {
public void doSomething();
public interface TestBean {
void doSomething();
}
public static class TestBeanImpl implements TestBean {
private static int constructionCount = 0;
public TestBeanImpl() {
@ -83,6 +87,7 @@ public class PrototypeTargetTests { @@ -83,6 +87,7 @@ public class PrototypeTargetTests {
public static class TestInterceptor implements MethodInterceptor {
private int invocationCount = 0;
@Override

10
spring-aop/src/test/java/org/springframework/aop/interceptor/ExposeInvocationInterceptorTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,7 +21,6 @@ import org.junit.Test; @@ -21,7 +21,6 @@ import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.Resource;
import org.springframework.tests.sample.beans.ITestBean;
import org.springframework.tests.sample.beans.TestBean;
@ -36,13 +35,11 @@ import static org.springframework.tests.TestResourceUtils.*; @@ -36,13 +35,11 @@ import static org.springframework.tests.TestResourceUtils.*;
*/
public class ExposeInvocationInterceptorTests {
private static final Resource CONTEXT =
qualifiedResource(ExposeInvocationInterceptorTests.class, "context.xml");
@Test
public void testXmlConfig() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(CONTEXT);
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
qualifiedResource(ExposeInvocationInterceptorTests.class, "context.xml"));
ITestBean tb = (ITestBean) bf.getBean("proxy");
String name = "tony";
tb.setName(name);
@ -74,6 +71,7 @@ abstract class ExposedInvocationTestBean extends TestBean { @@ -74,6 +71,7 @@ abstract class ExposedInvocationTestBean extends TestBean {
class InvocationCheckExposedInvocationTestBean extends ExposedInvocationTestBean {
@Override
protected void assertions(MethodInvocation invocation) {
assertTrue(invocation.getThis() == this);

17
spring-aop/src/test/java/org/springframework/aop/scope/ScopedProxyAutowireTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -22,7 +22,6 @@ import org.junit.Test; @@ -22,7 +22,6 @@ import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.Resource;
import static org.junit.Assert.*;
import static org.springframework.tests.TestResourceUtils.*;
@ -34,16 +33,12 @@ import static org.springframework.tests.TestResourceUtils.*; @@ -34,16 +33,12 @@ import static org.springframework.tests.TestResourceUtils.*;
*/
public class ScopedProxyAutowireTests {
private static final Resource SCOPED_AUTOWIRE_FALSE_CONTEXT =
qualifiedResource(ScopedProxyAutowireTests.class, "scopedAutowireFalse.xml");
private static final Resource SCOPED_AUTOWIRE_TRUE_CONTEXT =
qualifiedResource(ScopedProxyAutowireTests.class, "scopedAutowireTrue.xml");
@Test
public void testScopedProxyInheritsAutowireCandidateFalse() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(SCOPED_AUTOWIRE_FALSE_CONTEXT);
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
qualifiedResource(ScopedProxyAutowireTests.class, "scopedAutowireFalse.xml"));
assertTrue(Arrays.asList(bf.getBeanNamesForType(TestBean.class, false, false)).contains("scoped"));
assertTrue(Arrays.asList(bf.getBeanNamesForType(TestBean.class, true, false)).contains("scoped"));
assertFalse(bf.containsSingleton("scoped"));
@ -55,7 +50,9 @@ public class ScopedProxyAutowireTests { @@ -55,7 +50,9 @@ public class ScopedProxyAutowireTests {
@Test
public void testScopedProxyReplacesAutowireCandidateTrue() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(SCOPED_AUTOWIRE_TRUE_CONTEXT);
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
qualifiedResource(ScopedProxyAutowireTests.class, "scopedAutowireTrue.xml"));
assertTrue(Arrays.asList(bf.getBeanNamesForType(TestBean.class, true, false)).contains("scoped"));
assertTrue(Arrays.asList(bf.getBeanNamesForType(TestBean.class, false, false)).contains("scoped"));
assertFalse(bf.containsSingleton("scoped"));

5
spring-aop/src/test/java/org/springframework/aop/support/RegexpMethodPointcutAdvisorIntegrationTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -39,7 +39,8 @@ import static org.springframework.tests.TestResourceUtils.*; @@ -39,7 +39,8 @@ import static org.springframework.tests.TestResourceUtils.*;
public class RegexpMethodPointcutAdvisorIntegrationTests {
private static final Resource CONTEXT =
qualifiedResource(RegexpMethodPointcutAdvisorIntegrationTests.class, "context.xml");
qualifiedResource(RegexpMethodPointcutAdvisorIntegrationTests.class, "context.xml");
@Test
public void testSinglePattern() throws Throwable {

41
spring-aop/src/test/java/org/springframework/aop/target/HotSwappableTargetSourceTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -25,7 +25,6 @@ import org.springframework.aop.framework.ProxyFactory; @@ -25,7 +25,6 @@ import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.Resource;
import org.springframework.tests.aop.interceptor.SerializableNopInterceptor;
import org.springframework.tests.sample.beans.Person;
import org.springframework.tests.sample.beans.SerializablePerson;
@ -41,31 +40,31 @@ import static org.springframework.tests.TestResourceUtils.*; @@ -41,31 +40,31 @@ import static org.springframework.tests.TestResourceUtils.*;
*/
public class HotSwappableTargetSourceTests {
private static final Resource CONTEXT = qualifiedResource(HotSwappableTargetSourceTests.class, "context.xml");
/** Initial count value set in bean factory XML */
private static final int INITIAL_COUNT = 10;
private DefaultListableBeanFactory beanFactory;
@Before
public void setUp() throws Exception {
public void setup() {
this.beanFactory = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(this.beanFactory).loadBeanDefinitions(CONTEXT);
new XmlBeanDefinitionReader(this.beanFactory).loadBeanDefinitions(
qualifiedResource(HotSwappableTargetSourceTests.class, "context.xml"));
}
/**
* We must simulate container shutdown, which should clear threads.
*/
@After
public void tearDown() {
public void close() {
// Will call pool.close()
this.beanFactory.destroySingletons();
}
/**
* Check it works like a normal invoker
*
*/
@Test
public void testBasicFunctionality() {
@ -106,18 +105,13 @@ public class HotSwappableTargetSourceTests { @@ -106,18 +105,13 @@ public class HotSwappableTargetSourceTests {
assertEquals(target1.getCount(), proxied.getCount());
}
/**
*
* @param invalid
* @return the message
*/
private IllegalArgumentException testRejectsSwapToInvalidValue(Object invalid) {
@Test
public void testRejectsSwapToNull() {
HotSwappableTargetSource swapper = (HotSwappableTargetSource) beanFactory.getBean("swapper");
IllegalArgumentException aopex = null;
try {
swapper.swap(invalid);
fail("Shouldn't be able to swap to invalid value [" + invalid + "]");
swapper.swap(null);
fail("Shouldn't be able to swap to invalid value");
}
catch (IllegalArgumentException ex) {
// Ok
@ -126,19 +120,9 @@ public class HotSwappableTargetSourceTests { @@ -126,19 +120,9 @@ public class HotSwappableTargetSourceTests {
// It shouldn't be corrupted, it should still work
testBasicFunctionality();
return aopex;
assertTrue(aopex.getMessage().contains("null"));
}
@Test
public void testRejectsSwapToNull() {
IllegalArgumentException ex = testRejectsSwapToInvalidValue(null);
assertTrue(ex.getMessage().contains("null"));
}
// TODO test reject swap to wrong interface or class?
// how to decide what's valid?
@Test
public void testSerialization() throws Exception {
SerializablePerson sp1 = new SerializablePerson();
@ -165,4 +149,5 @@ public class HotSwappableTargetSourceTests { @@ -165,4 +149,5 @@ public class HotSwappableTargetSourceTests {
assertEquals(sp1.getName(), p.getName());
}
}

17
spring-aop/src/test/java/org/springframework/aop/target/PrototypeTargetSourceTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,11 +19,8 @@ package org.springframework.aop.target; @@ -19,11 +19,8 @@ package org.springframework.aop.target;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.Resource;
import org.springframework.tests.sample.beans.SideEffectBean;
import static org.junit.Assert.*;
@ -35,19 +32,20 @@ import static org.springframework.tests.TestResourceUtils.*; @@ -35,19 +32,20 @@ import static org.springframework.tests.TestResourceUtils.*;
*/
public class PrototypeTargetSourceTests {
private static final Resource CONTEXT = qualifiedResource(PrototypeTargetSourceTests.class, "context.xml");
/** Initial count value set in bean factory XML */
private static final int INITIAL_COUNT = 10;
private BeanFactory beanFactory;
private DefaultListableBeanFactory beanFactory;
@Before
public void setUp() throws Exception {
public void setup() {
this.beanFactory = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader((BeanDefinitionRegistry) this.beanFactory).loadBeanDefinitions(CONTEXT);
new XmlBeanDefinitionReader(this.beanFactory).loadBeanDefinitions(
qualifiedResource(PrototypeTargetSourceTests.class, "context.xml"));
}
/**
* Test that multiple invocations of the prototype bean will result
* in no change to visible state, as a new instance is used.
@ -66,5 +64,4 @@ public class PrototypeTargetSourceTests { @@ -66,5 +64,4 @@ public class PrototypeTargetSourceTests {
assertEquals(INITIAL_COUNT, prototype.getCount());
}
}

16
spring-aop/src/test/java/org/springframework/aop/target/ThreadLocalTargetSourceTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,7 +21,6 @@ import org.junit.Test; @@ -21,7 +21,6 @@ import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.Resource;
import org.springframework.tests.sample.beans.ITestBean;
import org.springframework.tests.sample.beans.SideEffectBean;
@ -34,26 +33,27 @@ import static org.springframework.tests.TestResourceUtils.*; @@ -34,26 +33,27 @@ import static org.springframework.tests.TestResourceUtils.*;
*/
public class ThreadLocalTargetSourceTests {
private static final Resource CONTEXT = qualifiedResource(ThreadLocalTargetSourceTests.class, "context.xml");
/** Initial count value set in bean factory XML */
private static final int INITIAL_COUNT = 10;
private DefaultListableBeanFactory beanFactory;
@Before
public void setUp() throws Exception {
public void setup() {
this.beanFactory = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(this.beanFactory).loadBeanDefinitions(CONTEXT);
new XmlBeanDefinitionReader(this.beanFactory).loadBeanDefinitions(
qualifiedResource(ThreadLocalTargetSourceTests.class, "context.xml"));
}
/**
* We must simulate container shutdown, which should clear threads.
*/
protected void tearDown() {
protected void close() {
this.beanFactory.destroySingletons();
}
/**
* Check we can use two different ThreadLocalTargetSources
* managing objects of different types without them interfering
@ -141,7 +141,7 @@ public class ThreadLocalTargetSourceTests { @@ -141,7 +141,7 @@ public class ThreadLocalTargetSourceTests {
}
/**
* Test for SPR-1442. Destroyed target should re-associated with thread and not throw NPE
* Test for SPR-1442. Destroyed target should re-associated with thread and not throw NPE.
*/
@Test
public void testReuseDestroyedTarget() {

31
spring-beans/src/test/java/org/springframework/beans/factory/ConcurrentBeanFactoryTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -50,10 +50,8 @@ import static org.springframework.tests.TestResourceUtils.*; @@ -50,10 +50,8 @@ import static org.springframework.tests.TestResourceUtils.*;
*/
public class ConcurrentBeanFactoryTests {
private static final Log logger = LogFactory.getLog(ConcurrentBeanFactoryTests.class);
private static final Resource CONTEXT = qualifiedResource(ConcurrentBeanFactoryTests.class, "context.xml");
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd");
private static final Date DATE_1, DATE_2;
static {
@ -66,27 +64,32 @@ public class ConcurrentBeanFactoryTests { @@ -66,27 +64,32 @@ public class ConcurrentBeanFactoryTests {
}
}
private static final Log logger = LogFactory.getLog(ConcurrentBeanFactoryTests.class);
private BeanFactory factory;
private final Set<TestRun> set = Collections.synchronizedSet(new HashSet<TestRun>());
private final Set<TestRun> set = Collections.synchronizedSet(new HashSet<>());
private Throwable ex;
private Throwable ex = null;
@Before
public void setUp() throws Exception {
public void setup() throws Exception {
Assume.group(TestGroup.PERFORMANCE);
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(factory).loadBeanDefinitions(CONTEXT);
factory.addPropertyEditorRegistrar(new PropertyEditorRegistrar() {
@Override
public void registerCustomEditors(PropertyEditorRegistry registry) {
registry.registerCustomEditor(Date.class, new CustomDateEditor((DateFormat) DATE_FORMAT.clone(), false));
}
});
new XmlBeanDefinitionReader(factory).loadBeanDefinitions(
qualifiedResource(ConcurrentBeanFactoryTests.class, "context.xml"));
factory.addPropertyEditorRegistrar(
registry -> registry.registerCustomEditor(Date.class,
new CustomDateEditor((DateFormat) DATE_FORMAT.clone(), false)));
this.factory = factory;
}
@Test
public void testSingleThread() {
for (int i = 0; i < 100; i++) {

11
spring-beans/src/test/java/org/springframework/beans/factory/annotation/CustomAutowireConfigurerTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,10 +21,8 @@ import org.junit.Test; @@ -21,10 +21,8 @@ import org.junit.Test;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.AutowireCandidateResolver;
import org.springframework.beans.factory.support.BeanDefinitionReader;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.Resource;
import static org.junit.Assert.*;
import static org.springframework.tests.TestResourceUtils.*;
@ -38,13 +36,12 @@ import static org.springframework.tests.TestResourceUtils.*; @@ -38,13 +36,12 @@ import static org.springframework.tests.TestResourceUtils.*;
*/
public class CustomAutowireConfigurerTests {
private static final Resource CONTEXT = qualifiedResource(CustomAutowireConfigurerTests.class, "context.xml");
@Test
public void testCustomResolver() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
BeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
reader.loadBeanDefinitions(CONTEXT);
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
qualifiedResource(CustomAutowireConfigurerTests.class, "context.xml"));
CustomAutowireConfigurer cac = new CustomAutowireConfigurer();
CustomResolver customResolver = new CustomResolver();
bf.setAutowireCandidateResolver(customResolver);

10
spring-beans/src/test/java/org/springframework/beans/factory/config/FieldRetrievingFactoryBeanTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -22,7 +22,6 @@ import org.junit.Test; @@ -22,7 +22,6 @@ import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.Resource;
import org.springframework.tests.sample.beans.TestBean;
import static org.junit.Assert.*;
@ -37,9 +36,6 @@ import static org.springframework.tests.TestResourceUtils.*; @@ -37,9 +36,6 @@ import static org.springframework.tests.TestResourceUtils.*;
*/
public class FieldRetrievingFactoryBeanTests {
private static final Resource CONTEXT =
qualifiedResource(FieldRetrievingFactoryBeanTests.class, "context.xml");
@Test
public void testStaticField() throws Exception {
FieldRetrievingFactoryBean fr = new FieldRetrievingFactoryBean();
@ -127,7 +123,9 @@ public class FieldRetrievingFactoryBeanTests { @@ -127,7 +123,9 @@ public class FieldRetrievingFactoryBeanTests {
@Test
public void testBeanNameSyntaxWithBeanFactory() throws Exception {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(CONTEXT);
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(
qualifiedResource(FieldRetrievingFactoryBeanTests.class, "context.xml"));
TestBean testBean = (TestBean) bf.getBean("testBean");
assertEquals(new Integer(Connection.TRANSACTION_SERIALIZABLE), testBean.getSomeIntegerArray()[0]);
assertEquals(new Integer(Connection.TRANSACTION_SERIALIZABLE), testBean.getSomeIntegerArray()[1]);

21
spring-beans/src/test/java/org/springframework/beans/factory/config/ObjectFactoryCreatingFactoryBeanTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -27,7 +27,6 @@ import org.springframework.beans.factory.BeanFactory; @@ -27,7 +27,6 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.Resource;
import org.springframework.util.SerializationTestUtils;
import static org.junit.Assert.*;
@ -42,25 +41,25 @@ import static org.springframework.tests.TestResourceUtils.*; @@ -42,25 +41,25 @@ import static org.springframework.tests.TestResourceUtils.*;
*/
public class ObjectFactoryCreatingFactoryBeanTests {
private static final Resource CONTEXT =
qualifiedResource(ObjectFactoryCreatingFactoryBeanTests.class, "context.xml");
private DefaultListableBeanFactory beanFactory;
@Before
public void setUp() {
public void setup() {
this.beanFactory = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(this.beanFactory).loadBeanDefinitions(CONTEXT);
new XmlBeanDefinitionReader(this.beanFactory).loadBeanDefinitions(
qualifiedResource(ObjectFactoryCreatingFactoryBeanTests.class, "context.xml"));
this.beanFactory.setSerializationId("test");
}
@After
public void tearDown() {
public void close() {
this.beanFactory.setSerializationId(null);
}
@Test
public void testFactoryOperation() throws Exception {
public void testFactoryOperation() {
FactoryTestBean testBean = beanFactory.getBean("factoryTestBean", FactoryTestBean.class);
ObjectFactory<?> objectFactory = testBean.getObjectFactory();
@ -82,7 +81,7 @@ public class ObjectFactoryCreatingFactoryBeanTests { @@ -82,7 +81,7 @@ public class ObjectFactoryCreatingFactoryBeanTests {
}
@Test
public void testProviderOperation() throws Exception {
public void testProviderOperation() {
ProviderTestBean testBean = beanFactory.getBean("providerTestBean", ProviderTestBean.class);
Provider<?> provider = testBean.getProvider();
@ -152,7 +151,7 @@ public class ObjectFactoryCreatingFactoryBeanTests { @@ -152,7 +151,7 @@ public class ObjectFactoryCreatingFactoryBeanTests {
}
@Test
public void testEnsureOFBFBReportsThatItActuallyCreatesObjectFactoryInstances() throws Exception {
public void testEnsureOFBFBReportsThatItActuallyCreatesObjectFactoryInstances() {
assertEquals("Must be reporting that it creates ObjectFactory instances (as per class contract).",
ObjectFactory.class, new ObjectFactoryCreatingFactoryBean().getObjectType());
}

13
spring-beans/src/test/java/org/springframework/beans/factory/config/SimpleScopeTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -25,7 +25,6 @@ import org.junit.Test; @@ -25,7 +25,6 @@ import org.junit.Test;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.Resource;
import org.springframework.tests.sample.beans.TestBean;
import static org.junit.Assert.*;
@ -40,12 +39,11 @@ import static org.springframework.tests.TestResourceUtils.*; @@ -40,12 +39,11 @@ import static org.springframework.tests.TestResourceUtils.*;
*/
public class SimpleScopeTests {
private static final Resource CONTEXT = qualifiedResource(SimpleScopeTests.class, "context.xml");
private DefaultListableBeanFactory beanFactory;
@Before
public void setUp() {
public void setup() {
beanFactory = new DefaultListableBeanFactory();
Scope scope = new NoOpScope() {
private int index;
@ -69,10 +67,11 @@ public class SimpleScopeTests { @@ -69,10 +67,11 @@ public class SimpleScopeTests {
assertEquals("myScope", scopeNames[0]);
assertSame(scope, beanFactory.getRegisteredScope("myScope"));
XmlBeanDefinitionReader xbdr = new XmlBeanDefinitionReader(beanFactory);
xbdr.loadBeanDefinitions(CONTEXT);
new XmlBeanDefinitionReader(beanFactory).loadBeanDefinitions(
qualifiedResource(SimpleScopeTests.class, "context.xml"));
}
@Test
public void testCanGetScopedObject() {
TestBean tb1 = (TestBean) beanFactory.getBean("usesScope");

10
spring-beans/src/test/java/org/springframework/beans/factory/parsing/CustomProblemReporterTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -24,7 +24,6 @@ import org.junit.Test; @@ -24,7 +24,6 @@ import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.Resource;
import org.springframework.tests.sample.beans.TestBean;
import static org.junit.Assert.*;
@ -37,8 +36,6 @@ import static org.springframework.tests.TestResourceUtils.*; @@ -37,8 +36,6 @@ import static org.springframework.tests.TestResourceUtils.*;
*/
public class CustomProblemReporterTests {
private static final Resource CONTEXT = qualifiedResource(CustomProblemReporterTests.class, "context.xml");
private CollatingProblemReporter problemReporter;
private DefaultListableBeanFactory beanFactory;
@ -47,16 +44,17 @@ public class CustomProblemReporterTests { @@ -47,16 +44,17 @@ public class CustomProblemReporterTests {
@Before
public void setUp() {
public void setup() {
this.problemReporter = new CollatingProblemReporter();
this.beanFactory = new DefaultListableBeanFactory();
this.reader = new XmlBeanDefinitionReader(this.beanFactory);
this.reader.setProblemReporter(this.problemReporter);
}
@Test
public void testErrorsAreCollated() {
this.reader.loadBeanDefinitions(CONTEXT);
this.reader.loadBeanDefinitions(qualifiedResource(CustomProblemReporterTests.class, "context.xml"));
assertEquals("Incorrect number of errors collated", 4, this.problemReporter.getErrors().length);
TestBean bean = (TestBean) this.beanFactory.getBean("validBean");

6
spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Decoder.java

@ -86,7 +86,8 @@ public abstract class AbstractJackson2Decoder extends Jackson2CodecSupport imple @@ -86,7 +86,8 @@ public abstract class AbstractJackson2Decoder extends Jackson2CodecSupport imple
public Flux<Object> decode(Publisher<DataBuffer> input, ResolvableType elementType,
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
Flux<TokenBuffer> tokens = Jackson2Tokenizer.tokenize(Flux.from(input), this.jsonFactory, true);
Flux<TokenBuffer> tokens = Jackson2Tokenizer.tokenize(
Flux.from(input), this.jsonFactory, getObjectMapper().getDeserializationContext(), true);
return decodeInternal(tokens, elementType, mimeType, hints);
}
@ -94,7 +95,8 @@ public abstract class AbstractJackson2Decoder extends Jackson2CodecSupport imple @@ -94,7 +95,8 @@ public abstract class AbstractJackson2Decoder extends Jackson2CodecSupport imple
public Mono<Object> decodeToMono(Publisher<DataBuffer> input, ResolvableType elementType,
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
Flux<TokenBuffer> tokens = Jackson2Tokenizer.tokenize(Flux.from(input), this.jsonFactory, false);
Flux<TokenBuffer> tokens = Jackson2Tokenizer.tokenize(
Flux.from(input), this.jsonFactory, getObjectMapper().getDeserializationContext(), false);
return decodeInternal(tokens, elementType, mimeType, hints).singleOrEmpty();
}

4
spring-web/src/main/java/org/springframework/http/codec/json/Jackson2CodecSupport.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -119,7 +119,7 @@ public abstract class Jackson2CodecSupport { @@ -119,7 +119,7 @@ public abstract class Jackson2CodecSupport {
@Nullable
protected MethodParameter getParameter(ResolvableType type) {
return type.getSource() instanceof MethodParameter ? (MethodParameter) type.getSource() : null;
return (type.getSource() instanceof MethodParameter ? (MethodParameter) type.getSource() : null);
}
@Nullable

77
spring-web/src/main/java/org/springframework/http/codec/json/Jackson2Tokenizer.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -26,13 +26,13 @@ import com.fasterxml.jackson.core.JsonParser; @@ -26,13 +26,13 @@ import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.async.ByteArrayFeeder;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.util.TokenBuffer;
import reactor.core.publisher.Flux;
import org.springframework.core.codec.DecodingException;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.util.Assert;
/**
* {@link Function} to transform a JSON stream of arbitrary size, byte array
@ -40,12 +40,16 @@ import org.springframework.util.Assert; @@ -40,12 +40,16 @@ import org.springframework.util.Assert;
* well-formed JSON object.
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @author Juergen Hoeller
* @since 5.0
*/
final class Jackson2Tokenizer {
private final JsonParser parser;
private final DeserializationContext deserializationContext;
private final boolean tokenizeArrayElements;
private TokenBuffer tokenBuffer;
@ -59,36 +63,16 @@ final class Jackson2Tokenizer { @@ -59,36 +63,16 @@ final class Jackson2Tokenizer {
private final ByteArrayFeeder inputFeeder;
private Jackson2Tokenizer(JsonParser parser, boolean tokenizeArrayElements) {
Assert.notNull(parser, "'parser' must not be null");
private Jackson2Tokenizer(
JsonParser parser, DeserializationContext deserializationContext, boolean tokenizeArrayElements) {
this.parser = parser;
this.deserializationContext = deserializationContext;
this.tokenizeArrayElements = tokenizeArrayElements;
this.tokenBuffer = new TokenBuffer(parser);
this.tokenBuffer = new TokenBuffer(parser, deserializationContext);
this.inputFeeder = (ByteArrayFeeder) this.parser.getNonBlockingInputFeeder();
}
/**
* Tokenize the given {@code Flux<DataBuffer>} into {@code Flux<TokenBuffer>}.
* @param dataBuffers the source data buffers
* @param jsonFactory the factory to use
* @param tokenizeArrayElements if {@code true} and the "top level" JSON
* object is an array, each element is returned individually, immediately
* after it is received.
* @return the result token buffers
*/
public static Flux<TokenBuffer> tokenize(Flux<DataBuffer> dataBuffers, JsonFactory jsonFactory,
boolean tokenizeArrayElements) {
try {
JsonParser parser = jsonFactory.createNonBlockingByteArrayParser();
Jackson2Tokenizer tokenizer = new Jackson2Tokenizer(parser, tokenizeArrayElements);
return dataBuffers.flatMap(tokenizer::tokenize, Flux::error, tokenizer::endOfInput);
}
catch (IOException ex) {
return Flux.error(ex);
}
}
private Flux<TokenBuffer> tokenize(DataBuffer dataBuffer) {
byte[] bytes = new byte[dataBuffer.readableByteCount()];
@ -100,8 +84,7 @@ final class Jackson2Tokenizer { @@ -100,8 +84,7 @@ final class Jackson2Tokenizer {
return parseTokenBufferFlux();
}
catch (JsonProcessingException ex) {
return Flux.error(new DecodingException(
"JSON decoding error: " + ex.getOriginalMessage(), ex));
return Flux.error(new DecodingException("JSON decoding error: " + ex.getOriginalMessage(), ex));
}
catch (IOException ex) {
return Flux.error(ex);
@ -114,8 +97,7 @@ final class Jackson2Tokenizer { @@ -114,8 +97,7 @@ final class Jackson2Tokenizer {
return parseTokenBufferFlux();
}
catch (JsonProcessingException ex) {
return Flux.error(new DecodingException(
"JSON decoding error: " + ex.getOriginalMessage(), ex));
return Flux.error(new DecodingException("JSON decoding error: " + ex.getOriginalMessage(), ex));
}
catch (IOException ex) {
return Flux.error(ex);
@ -128,12 +110,11 @@ final class Jackson2Tokenizer { @@ -128,12 +110,11 @@ final class Jackson2Tokenizer {
while (true) {
JsonToken token = this.parser.nextToken();
// SPR-16151: Smile data format uses null to separate documents
if ((token == JsonToken.NOT_AVAILABLE) ||
if (token == JsonToken.NOT_AVAILABLE ||
(token == null && (token = this.parser.nextToken()) == null)) {
break;
}
updateDepth(token);
if (!this.tokenizeArrayElements) {
processTokenNormal(token, result);
}
@ -164,10 +145,9 @@ final class Jackson2Tokenizer { @@ -164,10 +145,9 @@ final class Jackson2Tokenizer {
private void processTokenNormal(JsonToken token, List<TokenBuffer> result) throws IOException {
this.tokenBuffer.copyCurrentEvent(this.parser);
if ((token.isStructEnd() || token.isScalarValue()) &&
this.objectDepth == 0 && this.arrayDepth == 0) {
if ((token.isStructEnd() || token.isScalarValue()) && this.objectDepth == 0 && this.arrayDepth == 0) {
result.add(this.tokenBuffer);
this.tokenBuffer = new TokenBuffer(this.parser);
this.tokenBuffer = new TokenBuffer(this.parser, this.deserializationContext);
}
}
@ -177,11 +157,10 @@ final class Jackson2Tokenizer { @@ -177,11 +157,10 @@ final class Jackson2Tokenizer {
this.tokenBuffer.copyCurrentEvent(this.parser);
}
if (this.objectDepth == 0 &&
(this.arrayDepth == 0 || this.arrayDepth == 1) &&
if (this.objectDepth == 0 && (this.arrayDepth == 0 || this.arrayDepth == 1) &&
(token == JsonToken.END_OBJECT || token.isScalarValue())) {
result.add(this.tokenBuffer);
this.tokenBuffer = new TokenBuffer(this.parser);
this.tokenBuffer = new TokenBuffer(this.parser, this.deserializationContext);
}
}
@ -190,4 +169,26 @@ final class Jackson2Tokenizer { @@ -190,4 +169,26 @@ final class Jackson2Tokenizer {
(token == JsonToken.END_ARRAY && this.arrayDepth == 0));
}
/**
* Tokenize the given {@code Flux<DataBuffer>} into {@code Flux<TokenBuffer>}.
* @param dataBuffers the source data buffers
* @param jsonFactory the factory to use
* @param tokenizeArrayElements if {@code true} and the "top level" JSON object is
* an array, each element is returned individually immediately after it is received
* @return the resulting token buffers
*/
public static Flux<TokenBuffer> tokenize(Flux<DataBuffer> dataBuffers, JsonFactory jsonFactory,
DeserializationContext deserializationContext, boolean tokenizeArrayElements) {
try {
JsonParser parser = jsonFactory.createNonBlockingByteArrayParser();
Jackson2Tokenizer tokenizer = new Jackson2Tokenizer(parser, deserializationContext, tokenizeArrayElements);
return dataBuffers.flatMap(tokenizer::tokenize, Flux::error, tokenizer::endOfInput);
}
catch (IOException ex) {
return Flux.error(ex);
}
}
}

11
spring-web/src/main/java/org/springframework/web/context/support/GenericWebApplicationContext.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -39,11 +39,10 @@ import org.springframework.web.context.ServletContextAware; @@ -39,11 +39,10 @@ import org.springframework.web.context.ServletContextAware;
/**
* Subclass of {@link GenericApplicationContext}, suitable for web environments.
*
* <p>Implements the
* {@link org.springframework.web.context.ConfigurableWebApplicationContext},
* but is not intended for declarative setup in {@code web.xml}. Instead,
* it is designed for programmatic setup, for example for building nested contexts or
* for use within Spring 3.1 {@link org.springframework.web.WebApplicationInitializer org.springframework.web.WebApplicationInitializers}.
* <p>Implements {@link org.springframework.web.context.ConfigurableWebApplicationContext},
* but is not intended for declarative setup in {@code web.xml}. Instead, it is designed
* for programmatic setup, for example for building nested contexts or for use within
* {@link org.springframework.web.WebApplicationInitializer WebApplicationInitializers}.
*
* <p><b>If you intend to implement a WebApplicationContext that reads bean definitions
* from configuration files, consider deriving from AbstractRefreshableWebApplicationContext,

30
spring-web/src/test/java/org/springframework/http/codec/json/Jackson2JsonDecoderTests.java

@ -42,18 +42,13 @@ import org.springframework.http.MediaType; @@ -42,18 +42,13 @@ import org.springframework.http.MediaType;
import org.springframework.http.codec.Pojo;
import org.springframework.util.MimeType;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap;
import static java.util.Arrays.*;
import static java.util.Collections.*;
import static org.junit.Assert.*;
import static org.springframework.core.ResolvableType.forClass;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8;
import static org.springframework.http.MediaType.APPLICATION_STREAM_JSON;
import static org.springframework.http.MediaType.APPLICATION_XML;
import static org.springframework.http.codec.json.Jackson2JsonDecoder.JSON_VIEW_HINT;
import static org.springframework.http.codec.json.JacksonViewBean.MyJacksonView1;
import static org.springframework.http.codec.json.JacksonViewBean.MyJacksonView3;
import static org.springframework.core.ResolvableType.*;
import static org.springframework.http.MediaType.*;
import static org.springframework.http.codec.json.Jackson2JsonDecoder.*;
import static org.springframework.http.codec.json.JacksonViewBean.*;
/**
* Unit tests for {@link Jackson2JsonDecoder}.
@ -67,10 +62,12 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTestCase<Jackson2Js @@ -67,10 +62,12 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTestCase<Jackson2Js
private Pojo pojo2 = new Pojo("f2", "b2");
public Jackson2JsonDecoderTests() {
super(new Jackson2JsonDecoder());
}
@Override
@Test
public void canDecode() {
@ -83,7 +80,7 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTestCase<Jackson2Js @@ -83,7 +80,7 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTestCase<Jackson2Js
assertFalse(decoder.canDecode(forClass(Pojo.class), APPLICATION_XML));
}
@Test // SPR-15866
@Test // SPR-15866
public void canDecodeWithProvidedMimeType() {
MimeType textJavascript = new MimeType("text", "javascript", StandardCharsets.UTF_8);
Jackson2JsonDecoder decoder = new Jackson2JsonDecoder(new ObjectMapper(), textJavascript);
@ -212,7 +209,6 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTestCase<Jackson2Js @@ -212,7 +209,6 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTestCase<Jackson2Js
}
private static class BeanWithNoDefaultConstructor {
private final String property1;
@ -231,12 +227,14 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTestCase<Jackson2Js @@ -231,12 +227,14 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTestCase<Jackson2Js
public String getProperty2() {
return this.property2;
}
}
@JsonDeserialize(using = Deserializer.class)
public static class TestObject {
private int test;
public int getTest() {
return this.test;
}
@ -245,6 +243,7 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTestCase<Jackson2Js @@ -245,6 +243,7 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTestCase<Jackson2Js
}
}
public static class Deserializer extends StdDeserializer<TestObject> {
private static final long serialVersionUID = 1L;
@ -254,8 +253,7 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTestCase<Jackson2Js @@ -254,8 +253,7 @@ public class Jackson2JsonDecoderTests extends AbstractDecoderTestCase<Jackson2Js
}
@Override
public TestObject deserialize(JsonParser p,
DeserializationContext ctxt) throws IOException {
public TestObject deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
JsonNode node = p.readValueAsTree();
TestObject result = new TestObject();
result.setTest(node.get("test").asInt());

23
spring-web/src/test/java/org/springframework/http/codec/json/Jackson2TokenizerTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -37,19 +37,20 @@ import org.springframework.core.codec.DecodingException; @@ -37,19 +37,20 @@ import org.springframework.core.codec.DecodingException;
import org.springframework.core.io.buffer.AbstractLeakCheckingTestCase;
import org.springframework.core.io.buffer.DataBuffer;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static java.util.Arrays.*;
import static java.util.Collections.*;
/**
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @author Juergen Hoeller
*/
public class Jackson2TokenizerTests extends AbstractLeakCheckingTestCase {
private ObjectMapper objectMapper;
private JsonFactory jsonFactory;
private ObjectMapper objectMapper;
@Before
public void createParser() {
@ -57,6 +58,7 @@ public class Jackson2TokenizerTests extends AbstractLeakCheckingTestCase { @@ -57,6 +58,7 @@ public class Jackson2TokenizerTests extends AbstractLeakCheckingTestCase {
this.objectMapper = new ObjectMapper(this.jsonFactory);
}
@Test
public void doNotTokenizeArrayElements() {
testTokenize(
@ -185,7 +187,8 @@ public class Jackson2TokenizerTests extends AbstractLeakCheckingTestCase { @@ -185,7 +187,8 @@ public class Jackson2TokenizerTests extends AbstractLeakCheckingTestCase {
Flux<DataBuffer> source = Flux.just(buffer)
.concatWith(Flux.error(new RuntimeException()));
Flux<TokenBuffer> result = Jackson2Tokenizer.tokenize(source, this.jsonFactory, true);
Flux<TokenBuffer> result = Jackson2Tokenizer.tokenize(
source, this.jsonFactory, this.objectMapper.getDeserializationContext(), true);
StepVerifier.create(result)
.expectError(RuntimeException.class)
@ -195,7 +198,8 @@ public class Jackson2TokenizerTests extends AbstractLeakCheckingTestCase { @@ -195,7 +198,8 @@ public class Jackson2TokenizerTests extends AbstractLeakCheckingTestCase {
@Test // SPR-16521
public void jsonEOFExceptionIsWrappedAsDecodingError() {
Flux<DataBuffer> source = Flux.just(stringBuffer("{\"status\": \"noClosingQuote}"));
Flux<TokenBuffer> tokens = Jackson2Tokenizer.tokenize(source, this.jsonFactory, false);
Flux<TokenBuffer> tokens = Jackson2Tokenizer.tokenize(
source, this.jsonFactory, this.objectMapper.getDeserializationContext(), false);
StepVerifier.create(tokens)
.expectError(DecodingException.class)
@ -204,10 +208,9 @@ public class Jackson2TokenizerTests extends AbstractLeakCheckingTestCase { @@ -204,10 +208,9 @@ public class Jackson2TokenizerTests extends AbstractLeakCheckingTestCase {
private void testTokenize(List<String> source, List<String> expected, boolean tokenizeArrayElements) {
Flux<TokenBuffer> tokenBufferFlux = Jackson2Tokenizer.tokenize(
Flux.fromIterable(source).map(this::stringBuffer),
this.jsonFactory,
this.jsonFactory, this.objectMapper.getDeserializationContext(),
tokenizeArrayElements);
Flux<String> result = tokenBufferFlux
@ -234,7 +237,6 @@ public class Jackson2TokenizerTests extends AbstractLeakCheckingTestCase { @@ -234,7 +237,6 @@ public class Jackson2TokenizerTests extends AbstractLeakCheckingTestCase {
}
private static class JSONAssertConsumer implements Consumer<String> {
private final String expected;
@ -253,4 +255,5 @@ public class Jackson2TokenizerTests extends AbstractLeakCheckingTestCase { @@ -253,4 +255,5 @@ public class Jackson2TokenizerTests extends AbstractLeakCheckingTestCase {
}
}
}
}

16
src/docs/asciidoc/core.adoc

@ -10,16 +10,16 @@ @@ -10,16 +10,16 @@
This part of the reference documentation covers all the technologies that are
absolutely integral to the Spring Framework.
Foremost amongst these is the Spring Framework's Inversion of Control (IoC) container. A
thorough treatment of the Spring Framework's IoC container is closely followed by
comprehensive coverage of Spring's Aspect-Oriented Programming (AOP) technologies. The
Spring Framework has its own AOP framework, which is conceptually easy to understand
and which successfully addresses the 80% sweet spot of AOP requirements in Java
enterprise programming.
Foremost amongst these is the Spring Framework's Inversion of Control (IoC) container.
A thorough treatment of the Spring Framework's IoC container is closely followed by
comprehensive coverage of Spring's Aspect-Oriented Programming (AOP) technologies.
The Spring Framework has its own AOP framework, which is conceptually easy to
understand and which successfully addresses the 80% sweet spot of AOP requirements
in Java enterprise programming.
Coverage of Spring's integration with AspectJ (currently the richest -- in terms of
features -- and certainly most mature AOP implementation in the Java enterprise space) is
also provided.
features -- and certainly most mature AOP implementation in the Java enterprise space)
is also provided.
include::core/core-beans.adoc[leveloffset=+1]

26
src/docs/asciidoc/core/core-aop-api.adoc

@ -1,14 +1,10 @@ @@ -1,14 +1,10 @@
[[aop-api]]
= Spring AOP APIs
The previous chapter described the Spring's support for AOP with
@AspectJ and schema-based aspect definitions. In this chapter, we discuss the lower-level
Spring AOP APIs and the AOP support typically used in Spring 1.2 applications. For new
applications, we recommend the use of the Spring 2.0 and later AOP support described in
the previous chapter. However, when you work with existing applications (or when you read books
and articles), you may come across Spring 1.2-style examples. Spring 5 remains backwards
compatible with Spring 1.2, and everything described in this chapter is fully supported
in Spring 5.
The previous chapter described the Spring's support for AOP with @AspectJ and schema-based
aspect definitions. In this chapter, we discuss the lower-level Spring AOP APIs. For common
applications, we recommend the use of Spring AOP with AspectJ pointcuts as described in the
previous chapter.
@ -111,7 +107,7 @@ Since 2.0, the most important type of pointcut used by Spring is @@ -111,7 +107,7 @@ Since 2.0, the most important type of pointcut used by Spring is
`org.springframework.aop.aspectj.AspectJExpressionPointcut`. This is a pointcut that
uses an AspectJ-supplied library to parse an AspectJ pointcut expression string.
See the <<aop,previous chapter>> for a discussion of supported AspectJ pointcut primitives.
See the <<aop, previous chapter>> for a discussion of supported AspectJ pointcut primitives.
@ -241,8 +237,7 @@ following example shows how to subclass `StaticMethodMatcherPointcut`: @@ -241,8 +237,7 @@ following example shows how to subclass `StaticMethodMatcherPointcut`:
----
There are also superclasses for dynamic pointcuts.
You can use custom pointcuts with any advice type in Spring 1.0 RC2 and above.
You can use custom pointcuts with any advice type.
@ -996,8 +991,7 @@ to consider: @@ -996,8 +991,7 @@ to consider:
and included in the spring-core JAR. In other words, CGLIB-based AOP works "`out of
the box`", as do JDK dynamic proxies.
There is little performance difference between CGLIB proxying and dynamic proxies. As of
Spring 1.0, dynamic proxies are slightly faster. However, this may change in the future.
There is little performance difference between CGLIB proxying and dynamic proxies.
Performance should not be a decisive consideration in this case.
@ -1092,7 +1086,7 @@ we override the transaction propagation settings: @@ -1092,7 +1086,7 @@ 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
<<beans-child-bean-definitions,previously>>, so that it may not actually ever be
<<beans-child-bean-definitions, previously>>, so that it may not actually ever be
instantiated. Application contexts (but not simple bean factories), by default,
pre-instantiate all singletons. Therefore, it is important (at least for singleton beans)
that, if you have a (parent) bean definition that you intend to use only as a template,
@ -1226,9 +1220,7 @@ Depending on how you created the proxy, you can usually set a `frozen` flag. In @@ -1226,9 +1220,7 @@ Depending on how you created the proxy, you can usually set a `frozen` flag. In
case, the `Advised` `isFrozen()` method returns `true`, and any attempts to modify
advice through addition or removal results in an `AopConfigException`. The ability
to freeze the state of an advised object is useful in some cases (for example, to
prevent calling code removing a security interceptor). It may also be used in Spring 1.1
to allow aggressive optimization if runtime advice modification is known not to be
required.
prevent calling code removing a security interceptor).

448
src/docs/asciidoc/core/core-aop.adoc

@ -2,33 +2,31 @@ @@ -2,33 +2,31 @@
= Aspect Oriented Programming with Spring
Aspect-oriented Programming (AOP) complements Object-oriented Programming (OOP) by
providing another way of thinking about program structure. The key unit of modularity in
OOP is the class, whereas in AOP the unit of modularity is the aspect. Aspects
providing another way of thinking about program structure. The key unit of modularity
in OOP is the class, whereas in AOP the unit of modularity is the aspect. Aspects
enable the modularization of concerns (such as transaction management) that cut across
multiple types and objects. (Such concerns are often termed "`crosscutting`" concerns in
AOP literature.)
multiple types and objects. (Such concerns are often termed "`crosscutting`" concerns
in AOP literature.)
One of the key components of Spring is the AOP framework. While the Spring IoC
container does not depend on AOP (meaning you do not need to use AOP if you don't want
to), AOP complements Spring IoC to provide a very capable middleware solution.
.Spring 2.0+ AOP
.Spring AOP with AspectJ pointcuts
****
Spring 2.0 introduced a simpler and more powerful way of writing custom aspects by using
either a <<aop-schema,schema-based approach>> or the <<aop-ataspectj,@AspectJ annotation
style>>. Both of these styles offer fully typed advice and use of the AspectJ pointcut
language while still using Spring AOP for weaving.
This chapter discusses the Spring 2.0+ schema- and @AspectJ-based AOP support.
The lower-level AOP support, as commonly exposed in Spring 1.2 applications, is
discussed in <<aop-api,the following chapter>>.
Spring provides simple and powerful ways of writing custom aspects by using either a
<<aop-schema, schema-based approach>> or the <<aop-ataspectj, @AspectJ annotation style>>.
Both of these styles offer fully typed advice and use of the AspectJ pointcut language
while still using Spring AOP for weaving.
This chapter discusses the schema- and @AspectJ-based AOP support.
The lower-level AOP support is discussed in <<aop-api, the following chapter>>.
****
AOP is used in the Spring Framework to:
* Provide declarative enterprise services, especially as a replacement for EJB
declarative services. The most important such service is
<<transaction-declarative,declarative transaction management>>.
* Provide declarative enterprise services. The most important such service is
<<transaction-declarative, declarative transaction management>>.
* Let users implement custom aspects, complementing their use of OOP with AOP.
NOTE: If you are interested only in generic declarative services or other pre-packaged
@ -48,7 +46,7 @@ However, it would be even more confusing if Spring used its own terminology. @@ -48,7 +46,7 @@ However, it would be even more confusing if Spring used its own terminology.
* Aspect: A modularization of a concern that cuts across multiple classes.
Transaction management is a good example of a crosscutting concern in enterprise Java
applications. In Spring AOP, aspects are implemented by using regular classes
(the <<aop-schema,schema-based approach>>) or regular classes annotated with the
(the <<aop-schema, schema-based approach>>) or regular classes annotated with the
`@Aspect` annotation (the <<aop-ataspectj, @AspectJ style>>).
* Join point: A point during the execution of a program, such as the execution of a
method or the handling of an exception. In Spring AOP, a join point always
@ -104,14 +102,14 @@ the same thing. Using the most specific advice type provides a simpler programmi @@ -104,14 +102,14 @@ the same thing. Using the most specific advice type provides a simpler programmi
with less potential for errors. For example, you do not need to invoke the `proceed()`
method on the `JoinPoint` used for around advice, and, hence, you cannot fail to invoke it.
In Spring 2.0, all advice parameters are statically typed so that you work with advice
parameters of the appropriate type (the type of the return value from a method execution
for example) rather than `Object` arrays.
All advice parameters are statically typed so that you work with advice parameters of
the appropriate type (e.g. the type of the return value from a method execution) rather
than `Object` arrays.
The concept of join points matched by pointcuts is the key to AOP, which distinguishes
it from older technologies offering only interception. Pointcuts enable advice to be
targeted independently of the object-oriented hierarchy. For example, you can apply an around advice
providing declarative transaction management to a set of methods that span
targeted independently of the object-oriented hierarchy. For example, you can apply an
around advice providing declarative transaction management to a set of methods that span
multiple objects (such as all business operations in the service layer).
@ -149,8 +147,8 @@ frameworks such as AspectJ are valuable and that they are complementary, rather @@ -149,8 +147,8 @@ frameworks such as AspectJ are valuable and that they are complementary, rather
competition. Spring seamlessly integrates Spring AOP and IoC with AspectJ, to enable
all uses of AOP within a consistent Spring-based application
architecture. This integration does not affect the Spring AOP API or the AOP Alliance
API. Spring AOP remains backward-compatible. See <<aop-api,the following chapter>> for a
discussion of the Spring AOP APIs.
API. Spring AOP remains backward-compatible. See <<aop-api, the following chapter>>
for a discussion of the Spring AOP APIs.
[NOTE]
====
@ -171,8 +169,8 @@ configuration-style approach. The fact that this chapter chooses to introduce th @@ -171,8 +169,8 @@ configuration-style approach. The fact that this chapter chooses to introduce th
@AspectJ-style approach first should not be taken as an indication that the Spring team
favors the @AspectJ annotation-style approach over the Spring XML configuration-style.
See <<aop-choosing>> for a more complete discussion of the "`whys and wherefores`" of each
style.
See <<aop-choosing>> for a more complete discussion of the "`whys and wherefores`" of
each style.
====
@ -188,7 +186,7 @@ Spring AOP can also use CGLIB proxies. This is necessary to proxy classes rather @@ -188,7 +186,7 @@ Spring AOP can also use CGLIB proxies. This is necessary to proxy classes rather
interfaces. By default, CGLIB is used if a business object does not implement an
interface. As it is good practice to program to interfaces rather than classes, business
classes normally implement one or more business interfaces. It is possible to
<<aop-proxying,force the use of CGLIB>>, in those (hopefully rare) cases where you
<<aop-proxying, force the use of CGLIB>>, in those (hopefully rare) cases where you
need to advise a method that is not declared on an interface or where you need to
pass a proxied object to a method as a concrete type.
@ -209,8 +207,8 @@ interprets the same annotations as AspectJ 5, using a library supplied by Aspect @@ -209,8 +207,8 @@ interprets the same annotations as AspectJ 5, using a library supplied by Aspect
for pointcut parsing and matching. The AOP runtime is still pure Spring AOP, though, and
there is no dependency on the AspectJ compiler or weaver.
NOTE: Using the AspectJ compiler and weaver enables use of the full AspectJ language and is
discussed in <<aop-using-aspectj>>.
NOTE: Using the AspectJ compiler and weaver enables use of the full AspectJ language and
is discussed in <<aop-using-aspectj>>.
@ -259,9 +257,9 @@ element, as the following example shows: @@ -259,9 +257,9 @@ element, as the following example shows:
----
This assumes that you use schema support as described in
<<core.adoc#xsd-schemas, XML Schema-based configuration>>. See
<<core.adoc#xsd-schemas-aop, the AOP schema>> for how to import the tags in the `aop`
namespace.
<<core.adoc#xsd-schemas, XML Schema-based configuration>>.
See <<core.adoc#xsd-schemas-aop, the AOP schema>> for how to
import the tags in the `aop` namespace.
@ -273,8 +271,8 @@ class that is an @AspectJ aspect (has the `@Aspect` annotation) is automatically @@ -273,8 +271,8 @@ class that is an @AspectJ aspect (has the `@Aspect` annotation) is automatically
detected by Spring and used to configure Spring AOP. The next two examples show the
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:
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"]
@ -284,8 +282,8 @@ the `@Aspect` annotation: @@ -284,8 +282,8 @@ the `@Aspect` annotation:
</bean>
----
The second of the two examples shows the `NotVeryUsefulAspect` class definition, which is annotated with
the `org.aspectj.lang.annotation.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"]
@ -413,7 +411,7 @@ If a pointcut is strictly meant to be public-only, even in a CGLIB proxy scenari @@ -413,7 +411,7 @@ If a pointcut is strictly meant to be public-only, even in a CGLIB proxy scenari
potential non-public interactions through proxies, it needs to be defined accordingly.
If your interception needs include method calls or even constructors within the target
class, consider the use of Spring-driven <<aop-aj-ltw,native AspectJ weaving>> instead
class, consider the use of Spring-driven <<aop-aj-ltw, native AspectJ weaving>> instead
of Spring's proxy-based AOP framework. This constitutes a different mode of AOP usage
with different characteristics, so be sure to make yourself familiar with weaving
before making a decision.
@ -1032,8 +1030,8 @@ taken by Spring is simpler and a better match to its proxy-based, execution-only @@ -1032,8 +1030,8 @@ taken by Spring is simpler and a better match to its proxy-based, execution-only
semantics. You only need to be aware of this difference if you compile @AspectJ
aspects written for Spring and use `proceed` with arguments with the AspectJ compiler
and weaver. There is a way to write such aspects that is 100% compatible across both
Spring AOP and AspectJ, and this is discussed in the <<aop-ataspectj-advice-params,following section on advice
parameters>>.
Spring AOP and AspectJ, and this is discussed in the
<<aop-ataspectj-advice-params, following section on advice parameters>>.
The following example shows how to use around advice:
@ -1551,8 +1549,7 @@ of advice parameters. @@ -1551,8 +1549,7 @@ of advice parameters.
To use the aop namespace tags described in this section, you need to import the
`spring-aop` schema, as described in <<core.adoc#xsd-schemas,
XML Schema-based configuration>>.
See <<core.adoc#xsd-schemas-aop, the AOP schema>>
XML Schema-based configuration>>. See <<core.adoc#xsd-schemas-aop, the AOP schema>>
for how to import the tags in the `aop` namespace.
Within your Spring configurations, all aspect and advisor elements must be placed within
@ -1561,10 +1558,11 @@ application context configuration). An `<aop:config>` element can contain pointc @@ -1561,10 +1558,11 @@ application context configuration). An `<aop:config>` element can contain pointc
advisor, and aspect elements (note that these must be declared in that order).
WARNING: The `<aop:config>` style of configuration makes heavy use of Spring's
<<aop-autoproxy,auto-proxying>> mechanism. This can cause issues (such as advice not
being woven) if you already use explicit auto-proxying through the use of
`BeanNameAutoProxyCreator` or something similar. The recommended usage pattern is to use either
only the `<aop:config>` style or only the `AutoProxyCreator` style and never mix them.
<<aop-autoproxy, auto-proxying>> mechanism. This can cause issues (such as advice
not being woven) if you already use explicit auto-proxying through the use of
`BeanNameAutoProxyCreator` or something similar. The recommended usage pattern is to
use either only the `<aop:config>` style or only the `AutoProxyCreator` style and
never mix them.
@ -1618,10 +1616,9 @@ be defined as follows: @@ -1618,10 +1616,9 @@ be defined as follows:
----
Note that the pointcut expression itself is using the same AspectJ pointcut expression
language as described in <<aop-ataspectj>>. If you use the schema based
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:
language as described in <<aop-ataspectj>>. If you use the schema based 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"]
@ -2413,11 +2410,11 @@ The downside of the XML approach is that you cannot define the @@ -2413,11 +2410,11 @@ The downside of the XML approach is that you cannot define the
The @AspectJ style supports additional instantiation models and richer pointcut
composition. It has the advantage of keeping the aspect as a modular unit. It also has
the advantage that the @AspectJ aspects can be understood (and thus consumed) both by Spring
AOP and by AspectJ. So, if you later decide you need the capabilities of AspectJ to
implement additional requirements, you can easily migrate to an AspectJ-based
approach. On balance, the Spring team prefers the @AspectJ style whenever you have aspects
that do more than simple configuration of enterprise services.
the advantage that the @AspectJ aspects can be understood (and thus consumed) both by
Spring AOP and by AspectJ. So, if you later decide you need the capabilities of AspectJ
to implement additional requirements, you can easily migrate to a classic AspectJ setup.
On balance, the Spring team prefers the @AspectJ style for custom aspects beyond simple
configuration of enterprise services.
@ -2426,10 +2423,9 @@ that do more than simple configuration of enterprise services. @@ -2426,10 +2423,9 @@ that do more than simple configuration of enterprise services.
== Mixing Aspect Types
It is perfectly possible to mix @AspectJ style aspects by using the auto-proxying support,
schema-defined `<aop:aspect>` aspects, `<aop:advisor>` declared advisors, and even
proxies and interceptors defined with the Spring 1.2 style in the same configuration.
All of these are implemented by using the same underlying support mechanism and can
co-exist without any difficulty.
schema-defined `<aop:aspect>` aspects, `<aop:advisor>` declared advisors, and even proxies
and interceptors in other styles in the same configuration. All of these are implemented
by using the same underlying support mechanism and can co-exist without any difficulty.
@ -2438,29 +2434,26 @@ co-exist without any difficulty. @@ -2438,29 +2434,26 @@ co-exist without any difficulty.
== Proxying Mechanisms
Spring AOP uses either JDK dynamic proxies or CGLIB to create the proxy for a given
target object. (JDK dynamic proxies are preferred whenever you have a choice).
target object. JDK dynamic proxies are built into the JDK, whereas CGLIB is a common
open-source class definition library (repackaged into `spring-core`).
If the target object to be proxied implements at least one interface, a JDK dynamic
proxy is used. All of the interfaces implemented by the target type are
proxied. If the target object does not implement any interfaces, a CGLIB proxy is
created.
proxy is used. All of the interfaces implemented by the target type are proxied.
If the target object does not implement any interfaces, a CGLIB proxy is created.
If you want to force the use of CGLIB proxying (for example, to proxy every method
defined for the target object, not only those implemented by its interfaces), you can do
so. However, you should consider the following issues:
* `final` methods cannot be advised, as they cannot be overridden.
* As of Spring 3.2, it is no longer necessary to add CGLIB to your project classpath, as
CGLIB classes are repackaged under `org.springframework` and included directly in the
spring-core JAR. This means that CGLIB-based proxy support "`just works`", in the same
way that JDK dynamic proxies always have.
* As of Spring 4.0, the constructor of your proxied object is NOT called twice
any more, since the CGLIB proxy instance is created through Objenesis. Only if your
JVM does not allow for constructor bypassing, you might see double invocations and
defined for the target object, not only those implemented by its interfaces),
you can do so. However, you should consider the following issues:
* With CGLIB, `final` methods cannot be advised, as they cannot be overridden in
runtime-generated subclasses.
* As of Spring 4.0, the constructor of your proxied object is NOT called twice anymore,
since the CGLIB proxy instance is created through Objenesis. Only if your JVM does
not allow for constructor bypassing, you might see double invocations and
corresponding debug log entries from Spring's AOP support.
To force the use of CGLIB proxies, set the value of the `proxy-target-class` attribute of
the `<aop:config>` element to true, as follows:
To force the use of CGLIB proxies, set the value of the `proxy-target-class` attribute
of the `<aop:config>` element to true, as follows:
[source,xml,indent=0]
[subs="verbatim,quotes"]
@ -2471,8 +2464,8 @@ the `<aop:config>` element to true, as follows: @@ -2471,8 +2464,8 @@ the `<aop:config>` 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 `<aop:aspectj-autoproxy>` element to `true`, as
follows:
`proxy-target-class` attribute of the `<aop:aspectj-autoproxy>` element to `true`,
as follows:
[source,xml,indent=0]
[subs="verbatim,quotes"]
@ -2533,9 +2526,7 @@ image::images/aop-proxy-plain-pojo-call.png[] @@ -2533,9 +2526,7 @@ image::images/aop-proxy-plain-pojo-call.png[]
public class Main {
public static void main(String[] args) {
Pojo pojo = new SimplePojo();
// this is a direct method call on the 'pojo' reference
pojo.foo();
}
@ -2553,36 +2544,33 @@ image::images/aop-proxy-call.png[] @@ -2553,36 +2544,33 @@ image::images/aop-proxy-call.png[]
public class Main {
public static void main(String[] args) {
ProxyFactory factory = new ProxyFactory(new SimplePojo());
factory.addInterface(Pojo.class);
factory.addAdvice(new RetryAdvice());
Pojo pojo = (Pojo) factory.getProxy();
// this is a method call on the proxy!
pojo.foo();
}
}
----
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
object reference are calls on the proxy. As a result, the proxy can
delegate to all of the interceptors (advice) that are relevant to that particular method
call. However, once the call has finally reached the target object (the `SimplePojo`,
reference in this case), any method calls that it may make on itself, such as
`this.bar()` or `this.foo()`, are going to be invoked against the `this` reference,
and not the proxy. This has important implications. It means that self-invocation is
not going to result in the advice associated with a method invocation getting a
chance to execute.
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
object reference are calls on the proxy. As a result, the proxy can delegate to all of
the interceptors (advice) that are relevant to that particular method call. However,
once the call has finally reached the target object (the `SimplePojo`, reference in
this case), any method calls that it may make on itself, such as `this.bar()` or
`this.foo()`, are going to be invoked against the `this` reference, and not the proxy.
This has important implications. It means that self-invocation is not going to result
in the advice associated with a method invocation getting a chance to execute.
Okay, so what is to be done about this? The best approach (the term, "`best,`" is used loosely
here) is to refactor your code such that the self-invocation does not happen.
Okay, so what is to be done about this? The best approach (the term, "`best,`" is used
loosely here) is to refactor your code such that the self-invocation does not happen.
This does entail some work on your part, but it is the best, least-invasive approach.
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:
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"]
@ -2611,14 +2599,12 @@ following example shows: @@ -2611,14 +2599,12 @@ following example shows:
public class Main {
public static void main(String[] args) {
ProxyFactory factory = new ProxyFactory(new SimplePojo());
factory.adddInterface(Pojo.class);
factory.addAdvice(new RetryAdvice());
factory.setExposeProxy(true);
Pojo pojo = (Pojo) factory.getProxy();
// this is a method call on the proxy!
pojo.foo();
}
@ -2634,11 +2620,11 @@ it is not a proxy-based AOP framework. @@ -2634,11 +2620,11 @@ it is not a proxy-based AOP framework.
[[aop-aspectj-programmatic]]
== Programmatic Creation of @AspectJ Proxies
In addition to declaring aspects in your configuration by using either `<aop:config>` or
`<aop:aspectj-autoproxy>`, it is also possible to programmatically create proxies that
advise target objects. For the full details of Spring's AOP API, see the <<aop-api,next chapter>>.
Here, we want to focus on the ability to automatically create proxies by using @AspectJ
aspects.
In addition to declaring aspects in your configuration by using either `<aop:config>`
or `<aop:aspectj-autoproxy>`, it is also possible to programmatically create proxies
that advise target objects. For the full details of Spring's AOP API, see the
<<aop-api, next chapter>>. Here, we want to focus on the ability to automatically
create proxies by using @AspectJ aspects.
You can use the `org.springframework.aop.aspectj.annotation.AspectJProxyFactory` class
to create a proxy for a target object that is advised by one or more @AspectJ aspects.
@ -2748,13 +2734,12 @@ Spring now looks for a bean definition named `account` and uses that as the @@ -2748,13 +2734,12 @@ Spring now looks for a bean definition named `account` and uses that as the
definition to configure new `Account` instances.
You can also use autowiring to avoid having to specify a dedicated bean definition at
all. To have Spring apply autowiring, use the `autowire` property of the
`@Configurable` annotation. You can specify either `@Configurable(autowire=Autowire.BY_TYPE)` or
all. To have Spring apply autowiring, use the `autowire` property of the `@Configurable`
annotation. You can specify either `@Configurable(autowire=Autowire.BY_TYPE)` or
`@Configurable(autowire=Autowire.BY_NAME` for autowiring by type or by name,
respectively. As an alternative, as of Spring 2.5, it is preferable to specify explicit,
annotation-driven dependency injection for your `@Configurable` beans by using
`@Autowired` or `@Inject` at the field or method level (see <<beans-annotation-config>>
for further details).
respectively. As an alternative, it is preferable to specify explicit, annotation-driven
dependency injection for your `@Configurable` beans through `@Autowired` or `@Inject`
at the field or method level (see <<beans-annotation-config>> for further details).
Finally, you can enable Spring dependency checking for the object references in the newly
created and configured object by using the `dependencyCheck` attribute (for example,
@ -2764,13 +2749,13 @@ are not primitives or collections) have been set. @@ -2764,13 +2749,13 @@ are not primitives or collections) have been set.
Note that using the annotation on its own does nothing. It is the
`AnnotationBeanConfigurerAspect` in `spring-aspects.jar` that acts on the presence of
the annotation. In essence, the aspect says, "`after returning from the initialization of a
new object of a type annotated with `@Configurable`, configure the newly created object
the annotation. In essence, the aspect says, "`after returning from the initialization of
a new object of a type annotated with `@Configurable`, configure the newly created object
using Spring in accordance with the properties of the annotation`". In this context,
"`initialization`" refers to newly instantiated objects (for example, objects instantiated with
the `new` operator) as well as to `Serializable` objects that are undergoing
"`initialization`" refers to newly instantiated objects (for example, objects instantiated
with the `new` operator) as well as to `Serializable` objects that are undergoing
deserialization (for example, through
http://docs.oracle.com/javase/6/docs/api/java/io/Serializable.html[readResolve()]).
http://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html[readResolve()]).
[NOTE]
=====
@ -2786,7 +2771,7 @@ available for use in the body of the constructors, you need to define this on th @@ -2786,7 +2771,7 @@ available for use in the body of the constructors, you need to define this on th
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@Configurable(preConstruction=true)
@Configurable(preConstruction = true)
----
You can find more information about the language semantics of the various pointcut
@ -2811,7 +2796,6 @@ use Java-based configuration, you can add `@EnableSpringConfigured` to any @@ -2811,7 +2796,6 @@ use Java-based configuration, you can add `@EnableSpringConfigured` to any
@Configuration
@EnableSpringConfigured
public class AppConfig {
}
----
@ -2943,7 +2927,6 @@ fully qualified class names: @@ -2943,7 +2927,6 @@ fully qualified class names:
initialization(new(..)) &&
SystemArchitecture.inDomainModel() &&
this(beanInstance);
}
----
@ -3027,14 +3010,12 @@ per-`ClassLoader` basis, which is more fine-grained and which can make more @@ -3027,14 +3010,12 @@ per-`ClassLoader` basis, which is more fine-grained and which can make more
sense in a 'single-JVM-multiple-application' environment (such as is found in a typical
application server environment).
Further, <<aop-aj-ltw-environments,in certain environments>>, this support enables
Further, <<aop-aj-ltw-environments, in certain environments>>, this support enables
load-time weaving without making any modifications to the application server's launch
script that is needed to add `-javaagent:path/to/aspectjweaver.jar` or (as we
describe later in this section)
`-javaagent:path/to/org.springframework.instrument-{version}.jar` (previously named
`spring-agent.jar`). Developers modify one or more files that form the
application context to enable load-time weaving instead of relying on administrators who
typically are in charge of the deployment configuration, such as the launch script.
script that is needed to add `-javaagent:path/to/aspectjweaver.jar` or (as we describe
later in this section) `-javaagent:path/to/spring-instrument.jar`. Developers configure
the application context to enable load-time weaving instead of relying on administrators
who typically are in charge of the deployment configuration, such as the launch script.
Now that the sales pitch is over, let us first walk through a quick example of AspectJ
LTW that uses Spring, followed by detailed specifics about elements introduced in the
@ -3046,18 +3027,18 @@ https://github.com/spring-projects/spring-petclinic[Petclinic sample application @@ -3046,18 +3027,18 @@ https://github.com/spring-projects/spring-petclinic[Petclinic sample application
==== A First Example
Assume that you are an application developer who has been tasked with diagnosing
the cause of some performance problems in a system. Rather than break out a profiling
tool, we are going to switch on a simple profiling aspect that lets us
quickly get some performance metrics. We can then apply a finer-grained
profiling tool to that specific area immediately afterwards.
the cause of some performance problems in a system. Rather than break out a
profiling tool, we are going to switch on a simple profiling aspect that lets us
quickly get some performance metrics. We can then apply a finer-grained profiling
tool to that specific area immediately afterwards.
NOTE: The example presented here uses XML configuration. You can also
configure and use @AspectJ with <<beans-java,Java configuration>>.
Specifically, you can use the `@EnableLoadTimeWeaving` annotation as an alternative to
`<context:load-time-weaver/>` (see <<aop-aj-ltw-spring,below>> for details).
NOTE: The example presented here uses XML configuration. You can also configure and
use @AspectJ with <<beans-java, Java configuration>>. Specifically, you can use the
`@EnableLoadTimeWeaving` annotation as an alternative to `<context:load-time-weaver/>`
(see <<aop-aj-ltw-spring, below>> for details).
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:
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"]
@ -3091,10 +3072,10 @@ profiler that uses the @AspectJ-style of aspect declaration: @@ -3091,10 +3072,10 @@ profiler that uses the @AspectJ-style of aspect declaration:
}
----
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:
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"]
@ -3115,12 +3096,13 @@ namely the presence of a file (or files) on the Java classpath called @@ -3115,12 +3096,13 @@ namely the presence of a file (or files) on the Java classpath called
</aspectj>
----
Now we can move on to the Spring-specific portion of the configuration. We need to configure a
`LoadTimeWeaver` (explained later). This load-time
weaver is the essential component responsible for weaving the aspect configuration in
one or more `META-INF/aop.xml` files into the classes in your application. The good
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:
Now we can move on to the Spring-specific portion of the configuration. We need
to configure a `LoadTimeWeaver` (explained later). This load-time weaver is the
essential component responsible for weaving the aspect configuration in one or
more `META-INF/aop.xml` files into the classes in your application. The good
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"]
@ -3145,8 +3127,8 @@ are some more options that you can specify, but these are detailed later), as ca @@ -3145,8 +3127,8 @@ 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:
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"]
@ -3158,11 +3140,10 @@ file, and the Spring configuration) are in place, we can create the following dr @@ -3158,11 +3140,10 @@ file, and the Spring configuration) are in place, we can create the following dr
public final class Main {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml", Main.class);
EntitlementCalculationService entitlementCalculationService
= (EntitlementCalculationService) ctx.getBean("entitlementCalculationService");
EntitlementCalculationService entitlementCalculationService =
(EntitlementCalculationService) ctx.getBean("entitlementCalculationService");
// the profiling aspect is 'woven' around this method execution
entitlementCalculationService.calculateEntitlement();
@ -3172,8 +3153,8 @@ file, and the Spring configuration) are in place, we can create the following dr @@ -3172,8 +3153,8 @@ 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:
However, for this example, we use a Java agent (supplied with Spring) to switch on LTW.
We use the following command to run the `Main` class shown earlier:
[literal]
[subs="verbatim,quotes"]
@ -3182,7 +3163,7 @@ java -javaagent:C:/projects/foo/lib/global/spring-instrument.jar foo.Main @@ -3182,7 +3163,7 @@ 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
http://docs.oracle.com/javase/8/docs/api/java/lang/instrument/package-summary.html[agents
to instrument programs that run on the JVM]. The Spring Framework ships with such an
agent, the `InstrumentationSavingAgent`, which is packaged in the
`spring-instrument.jar` that was supplied as the value of the `-javaagent` argument in
@ -3220,11 +3201,10 @@ result: @@ -3220,11 +3201,10 @@ result:
public final class Main {
public static void main(String[] args) {
new ClassPathXmlApplicationContext("beans.xml", Main.class);
EntitlementCalculationService entitlementCalculationService =
new StubEntitlementCalculationService();
new StubEntitlementCalculationService();
// the profiling aspect will be 'woven' around this method execution
entitlementCalculationService.calculateEntitlement();
@ -3261,8 +3241,9 @@ Furthermore, the compiled aspect classes need to be available on the classpath. @@ -3261,8 +3241,9 @@ Furthermore, the compiled aspect classes need to be available on the classpath.
The AspectJ LTW infrastructure is configured by using one or more `META-INF/aop.xml`
files that are on the Java classpath (either directly or, more typically, in jar files).
The structure and contents of this file is detailed in the LTW part http://www.eclipse.org/aspectj/doc/released/devguide/ltw-configuration.html[AspectJ reference
documentation]. Because the aop.xml file is 100% AspectJ, we do not describe it further here.
The structure and contents of this file is detailed in the LTW part of the
http://www.eclipse.org/aspectj/doc/released/devguide/ltw-configuration.html[AspectJ reference
documentation]. Because the `aop.xml` file is 100% AspectJ, we do not describe it further here.
[[aop-aj-ltw-libraries]]
@ -3271,10 +3252,10 @@ documentation]. Because the aop.xml file is 100% AspectJ, we do not describe it @@ -3271,10 +3252,10 @@ documentation]. Because the aop.xml file is 100% AspectJ, we do not describe it
At minimum, you need the following libraries to use the Spring Framework's support
for AspectJ LTW:
* `spring-aop.jar` (version 2.5 or later, plus all mandatory dependencies)
* `aspectjweaver.jar` (version 1.6.8 or later)
* `spring-aop.jar`
* `aspectjweaver.jar`
If you use the <<aop-aj-ltw-environment-generic,Spring-provided agent to enable
If you use the <<aop-aj-ltw-environment-generic, Spring-provided agent to enable
instrumentation>>, you also need:
* `spring-instrument.jar`
@ -3309,7 +3290,6 @@ which typically is done by using the `@EnableLoadTimeWeaving` annotation, as fol @@ -3309,7 +3290,6 @@ which typically is done by using the `@EnableLoadTimeWeaving` annotation, as fol
@Configuration
@EnableLoadTimeWeaving
public class AppConfig {
}
----
@ -3335,50 +3315,50 @@ Alternatively, if you prefer XML-based configuration, use the @@ -3335,50 +3315,50 @@ Alternatively, if you prefer XML-based configuration, use the
</beans>
----
The preceding configuration automatically defines and registers a number of LTW-specific infrastructure
beans, such as a `LoadTimeWeaver` and an `AspectJWeavingEnabler`, for you.
The preceding configuration automatically defines and registers a number of LTW-specific
infrastructure beans, such as a `LoadTimeWeaver` and an `AspectJWeavingEnabler`, for you.
The default `LoadTimeWeaver` is the `DefaultContextLoadTimeWeaver` class, which attempts
to decorate an automatically detected `LoadTimeWeaver`. The exact type of
`LoadTimeWeaver` that is "`automatically detected`" is dependent upon your runtime
environment. The following table summarizes various `LoadTimeWeaver` implementations:
to decorate an automatically detected `LoadTimeWeaver`. The exact type of `LoadTimeWeaver`
that is "`automatically detected`" is dependent upon your runtime environment.
The following table summarizes various `LoadTimeWeaver` implementations:
[[aop-aj-ltw-spring-env-impls]]
.DefaultContextLoadTimeWeaver LoadTimeWeavers
|===
| Runtime Environment| `LoadTimeWeaver` implementation
| Running in Oracle's
http://www.oracle.com/technetwork/middleware/weblogic/overview/index-085209.html[WebLogic]
| `WebLogicLoadTimeWeaver`
| Running in Oracle's http://glassfish.dev.java.net/[GlassFish]
| `GlassFishLoadTimeWeaver`
| Running in http://tomcat.apache.org/[Apache Tomcat]
| `TomcatLoadTimeWeaver`
| Running in http://glassfish.dev.java.net/[GlassFish] (limited to EAR deployments)
| `GlassFishLoadTimeWeaver`
| Running in Red Hat's http://www.jboss.org/jbossas/[JBoss AS] or http://www.wildfly.org/[WildFly]
| `JBossLoadTimeWeaver`
| Running in IBM's http://www-01.ibm.com/software/webservers/appserv/was/[WebSphere]
| `WebSphereLoadTimeWeaver`
| JVM started with Spring `InstrumentationSavingAgent` (`java
-javaagent:path/to/spring-instrument.jar`)
| Running in Oracle's
http://www.oracle.com/technetwork/middleware/weblogic/overview/index-085209.html[WebLogic]
| `WebLogicLoadTimeWeaver`
| JVM started with Spring `InstrumentationSavingAgent`
(`java -javaagent:path/to/spring-instrument.jar`)
| `InstrumentationLoadTimeWeaver`
| Fallback, expecting the underlying ClassLoader to follow common conventions (for example
applicable to `TomcatInstrumentableClassLoader` and http://www.caucho.com/[Resin])
| Fallback, expecting the underlying ClassLoader to follow common conventions
(namely `addTransformer` and optionally a `getThrowawayClassLoader` method)
| `ReflectiveLoadTimeWeaver`
|===
Note that the table lists only the `LoadTimeWeavers` that are autodetected when you use the
`DefaultContextLoadTimeWeaver`. You can specify exactly which
`LoadTimeWeaver` implementation to use.
Note that the table lists only the `LoadTimeWeavers` that are autodetected when you
use the `DefaultContextLoadTimeWeaver`. You can specify exactly which `LoadTimeWeaver`
implementation to use.
To specify a specific `LoadTimeWeaver` with Java configuration, implement the
`LoadTimeWeavingConfigurer` interface and override the `getLoadTimeWeaver()` method. The
following example specifies a `ReflectiveLoadTimeWeaver`:
`LoadTimeWeavingConfigurer` interface and override the `getLoadTimeWeaver()` method.
The following example specifies a `ReflectiveLoadTimeWeaver`:
[source,java,indent=0]
[subs="verbatim,quotes"]
@ -3426,10 +3406,9 @@ the `org.aspectj.weaver.loadtime` package) class. See the class-level javadoc of @@ -3426,10 +3406,9 @@ the `org.aspectj.weaver.loadtime` package) class. See the class-level javadoc of
`ClassPreProcessorAgentAdapter` class for further details, because the specifics of how
the weaving is actually effected is beyond the scope of this document.
There is one final attribute of the configuration left to discuss: the
`aspectjWeaving` attribute (or `aspectj-weaving` if you use XML). This
attribute controls whether LTW is enabled or not.
It accepts one of three possible values, with the default value being
There is one final attribute of the configuration left to discuss: the `aspectjWeaving`
attribute (or `aspectj-weaving` if you use XML). This attribute controls whether LTW
is enabled or not. It accepts one of three possible values, with the default value being
`autodetect` if the attribute is not present. The following table summarizes the three
possible values:
@ -3460,69 +3439,17 @@ This last section contains any additional settings and configuration that you ne @@ -3460,69 +3439,17 @@ This last section contains any additional settings and configuration that you ne
when you use Spring's LTW support in environments such as application servers and web
containers.
[[aop-aj-ltw-environment-tomcat]]
===== Tomcat
Historically, http://tomcat.apache.org/[Apache Tomcat]'s default class loader did not
support class transformation, which is why Spring provides an enhanced implementation
that addresses this need. Named `TomcatInstrumentableClassLoader`, the loader works on
Tomcat 6.0 and above.
[[aop-aj-ltw-environments-tomcat-jboss-etc]]
===== Tomcat, JBoss, WebSphere, WebLogic
TIP: Do not define `TomcatInstrumentableClassLoader` on Tomcat 8.0 and higher.
Instead, let Spring automatically use Tomcat's new native `InstrumentableClassLoader`
facility through the `TomcatLoadTimeWeaver` strategy.
Tomcat, JBoss/WildFly, IBM WebSphere Application Server and Oracle WebLogic Server all
provide a general app `ClassLoader` that is capable of local instrumentation. Spring's
native LTW may leverage those ClassLoader implementations to provide AspectJ weaving.
You can simply enable load-time weaving, as <<aop-using-aspectj, described earlier>>.
Specifically, you do not need to modify the JVM launch script to add
`-javaagent:path/to/spring-instrument.jar`.
If you still need to use `TomcatInstrumentableClassLoader`, you can register it
individually for each web application as follows:
. Copy `org.springframework.instrument.tomcat.jar` into `$CATALINA_HOME/lib`, where
`$CATALINA_HOME` represents the root of the Tomcat installation
. 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"]
----
<Context path="/myWebApp" docBase="/my/webApp/location">
<Loader
loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>
</Context>
----
Apache Tomcat 6.0+ supports several context locations:
* Server configuration file: `$CATALINA_HOME/conf/server.xml`
* Default context configuration: `$CATALINA_HOME/conf/context.xml`, which affects all
deployed web applications
* A per-web application configuration, which can be deployed either on the server-side at
`$CATALINA_HOME/conf/[enginename]/[hostname]/[webapp]-context.xml` or embedded
inside the web-app archive at `META-INF/context.xml`
For efficiency, we recommend the embedded per-web application configuration style, because it
impacts only applications that use the custom class loader and does not require any
changes to the server configuration. See the Tomcat 6.0.x
http://tomcat.apache.org/tomcat-6.0-doc/config/context.html[documentation] for more
details about available context locations.
Alternatively, consider using the Spring-provided generic VM agent, to be specified
in Tomcat's launch script (described earlier in this section). This makes instrumentation available to all
deployed web applications, no matter the `ClassLoader` on which they happen to run.
[[aop-aj-ltw-environments-weblogic-oc4j-resin-glassfish-jboss]]
===== WebLogic, WebSphere, Resin, GlassFish, and JBoss
Recent versions of WebLogic Server (version 10 and above), IBM WebSphere Application
Server (version 7 and above), Resin (version 3.1 and above), and JBoss (version 6.x or above) provide a
`ClassLoader` that is capable of local instrumentation. Spring's native LTW leverages such
ClassLoader implementations to enable AspectJ weaving. You can enable LTW by activating
load-time weaving, as <<aop-using-aspectj,described earlier>>. Specifically, you do not need to modify the
launch script to add `-javaagent:path/to/spring-instrument.jar`.
Note that the GlassFish instrumentation-capable `ClassLoader` is available only in its EAR
environment. For GlassFish web applications, follow the Tomcat setup instructions
<<aop-aj-ltw-environment-tomcat,outlined earlier>>.
Note that, on JBoss 6.x, you need to disable the app server scanning to prevent it from
Note that on JBoss, you may need to disable the app server scanning to prevent it from
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:
@ -3532,31 +3459,28 @@ to your artifact a file named `WEB-INF/jboss-scanning.xml` with the following co @@ -3532,31 +3459,28 @@ to your artifact a file named `WEB-INF/jboss-scanning.xml` with the following co
<scanning xmlns="urn:jboss:scanning:1.0"/>
----
[[aop-aj-ltw-environment-generic]]
[[aop-aj-ltw-environments-generic]]
===== Generic Java Applications
When class instrumentation is required in environments that do not support or are not
supported by the existing `LoadTimeWeaver` implementations, a JDK agent can be the only
solution. For such cases, Spring provides `InstrumentationLoadTimeWeaver`, which
requires a Spring-specific (but very general) VM agent,
`org.springframework.instrument-{version}.jar` (previously named `spring-agent.jar`).
When class instrumentation is required in environments that are not supported by
specific `LoadTimeWeaver` implementations, a JVM agent is the general solution.
For such cases, Spring provides `InstrumentationLoadTimeWeaver` which requires a
Spring-specific (but very general) JVM agent, `spring-instrument.jar`, autodetected
by common `@EnableLoadTimeWeaving` and `<context:load-time-weaver/>` setups.
To use it, you must start the virtual machine with the Spring agent by supplying the
following JVM options:
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
-javaagent:/path/to/spring-instrument.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).
Additionally, the JDK agent instruments the entire VM, which can be expensive.
For performance reasons, we recommend that you use this configuration only if your target
environment (such as http://www.eclipse.org/jetty/[Jetty]) does not have (or does not
support) a dedicated LTW.
Note that this requires modification of the JVM launch script, which may prevent you
from using this in application server environments (depending on your server and your
operation policies). That said, for one-app-per-JVM deployments such as standalone
Spring Boot applications, you typically control the entire JVM setup in any case.

149
src/docs/asciidoc/core/core-appendix.adoc

@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
[[xsd-schemas]]
== XML Schemas
@ -36,7 +37,6 @@ correct schema so that the tags in the `util` namespace are available to you): @@ -36,7 +37,6 @@ correct schema so that the tags in the `util` namespace are available to you):
----
[[xsd-schemas-util-constant]]
==== Using `<util:constant/>`
@ -72,8 +72,6 @@ developer's intent ("`inject this constant value`"), and it reads better: @@ -72,8 +72,6 @@ developer's intent ("`inject this constant value`"), and it reads better:
</bean>
----
[[xsd-schemas-util-frfb]]
===== Setting a Bean Property or Constructor Argument from a Field Value
@ -127,10 +125,9 @@ described in the API documentation for the @@ -127,10 +125,9 @@ described in the API documentation for the
class.
Injecting enumeration values into beans as either property or constructor arguments is
easy to do in Spring. You do not actually have to do anything or know
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:
easy to do in Spring. You do not actually have to do anything or know 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"]
@ -170,7 +167,6 @@ Now consider the following setter of type `PersistenceContextType` and the corre @@ -170,7 +167,6 @@ Now consider the following setter of type `PersistenceContextType` and the corre
----
[[xsd-schemas-util-property-path]]
==== Using `<util:property-path/>`
@ -327,7 +323,6 @@ The following example uses a `util:properties` element to make a more concise re @@ -327,7 +323,6 @@ The following example uses a `util:properties` element to make a more concise re
----
[[xsd-schemas-util-list]]
==== Using `<util:list/>`
@ -386,7 +381,6 @@ following configuration: @@ -386,7 +381,6 @@ following configuration:
If no `list-class` attribute is supplied, the container chooses a `List` implementation.
[[xsd-schemas-util-map]]
==== Using `<util:map/>`
@ -445,7 +439,6 @@ following configuration: @@ -445,7 +439,6 @@ following configuration:
If no `'map-class'` attribute is supplied, the container chooses a `Map` implementation.
[[xsd-schemas-util-set]]
==== Using `<util:set/>`
@ -558,69 +551,64 @@ available to you: @@ -558,69 +551,64 @@ available to you:
----
[[xsd-schemas-context-pphc]]
==== Using `<property-placeholder/>`
This element activates the replacement of `${...}` placeholders, which are resolved against a
specified properties file (as a <<core.adoc#resources,Spring resource location>>). This element
is a convenience mechanism that sets up a <<core.adoc#beans-factory-placeholderconfigurer,
`PropertySourcesPlaceholderConfigurer`>> for you. If you need more control over the
`PropertySourcesPlaceholderConfigurer`, you can explicitly define one yourself.
specified properties file (as a <<core.adoc#resources, Spring resource location>>). This element is
a convenience mechanism that sets up a <<core.adoc#beans-factory-placeholderconfigurer,
`PropertyPlaceholderConfigurer`>> for you. If you need more control over the
`PropertyPlaceholderConfigurer`, you can explicitly define one yourself.
[[xsd-schemas-context-ac]]
==== Using `<annotation-config/>`
This element activates the Spring infrastructure to detect annotations in bean
classes:
This element activates the Spring infrastructure to detect annotations in bean classes:
* Spring's <<core.adoc#beans-required-annotation, `@Required`>> and
<<core.adoc#beans-annotation-config, `@Autowired`>>
* JSR 250's `@PostConstruct`,
`@PreDestroy` and `@Resource` (if available)
* JPA's `@PersistenceContext` and
`@PersistenceUnit` (if available).
* Spring's <<core.adoc#beans-factory-metadata, `@Configuration`>> model
* <<core.adoc#beans-annotation-config, `@Autowired`/`@Inject`>> and `@Value`
* JSR-250's `@Resource`, `@PostConstruct` and `@PreDestroy` (if available)
* JPA's `@PersistenceContext` and `@PersistenceUnit` (if available)
* Spring's <<core.adoc#context-functionality-events-annotation, `@EventListener`>>
Alternatively, you can choose to explicitly activate the
individual `BeanPostProcessors` for those annotations.
Alternatively, you can choose to explicitly activate the individual `BeanPostProcessors`
for those annotations.
NOTE: This element does not activate processing of Spring's
<<data-access.adoc#transaction-declarative-annotations, `@Transactional`>> annotation. You can use the
<<data-access.adoc#tx-decl-explained, `<tx:annotation-driven/>`>> element for that purpose.
<<data-access.adoc#transaction-declarative-annotations, `@Transactional`>> annotation;
you can use the <<data-access.adoc#tx-decl-explained, `<tx:annotation-driven/>`>>
element for that purpose. Similarly, Spring's
<<integration.adoc#cache-annotations, caching annotations>> need to be explicitly
<<integration.adoc#cache-annotation-enable, enabled>> as well.
[[xsd-schemas-context-component-scan]]
==== Using `<component-scan/>`
This element is detailed in <<core.adoc#beans-annotation-config,
Annotation-based container configuration>>.
This element is detailed in the section on <<core.adoc#beans-annotation-config,
annotation-based container configuration>>.
[[xsd-schemas-context-ltw]]
==== Using `<load-time-weaver/>`
This element is detailed in <<core.adoc#aop-aj-ltw,
Load-time weaving with AspectJ in the Spring Framework>>.
This element is detailed in the section on <<core.adoc#aop-aj-ltw,
load-time weaving with AspectJ in the Spring Framework>>.
[[xsd-schemas-context-sc]]
==== Using `<spring-configured/>`
This element is detailed in <<core.adoc#aop-atconfigurable,
Using AspectJ to dependency inject domain objects with Spring>>.
This element is detailed in the section on <<core.adoc#aop-atconfigurable,
using AspectJ to dependency inject domain objects with Spring>>.
[[xsd-schemas-context-mbe]]
==== Using `<mbean-export/>`
This element is detailed in <<integration.adoc#jmx-context-mbeanexport,
Configuring annotation based MBean export>>.
This element is detailed in the section on <<integration.adoc#jmx-context-mbeanexport,
configuring annotation-based MBean export>>.
@ -630,8 +618,8 @@ Configuring annotation based MBean export>>. @@ -630,8 +618,8 @@ Configuring annotation based MBean export>>.
Last but not least, we have the elements in the `beans` schema. These elements
have been in Spring since the very dawn of the framework. Examples of the various elements
in the `beans` schema are not shown here because they are quite comprehensively covered
in <<core.adoc#beans-factory-properties-detailed,Dependencies and configuration in detail>>
(and, indeed, in that entire <<core.adoc#beans,chapter>>).
in <<core.adoc#beans-factory-properties-detailed, dependencies and configuration in detail>>
(and, indeed, in that entire <<core.adoc#beans, chapter>>).
Note that you can add zero or more key-value pairs to `<bean/>` XML definitions.
What, if anything, is done with this extra metadata is totally up to your own custom
@ -660,10 +648,9 @@ as it stands). @@ -660,10 +648,9 @@ 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 metadata.
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
metadata.
@ -683,11 +670,11 @@ Spring distribution, you should first read the appendix entitled <<xsd-config>>. @@ -683,11 +670,11 @@ Spring distribution, you should first read the appendix entitled <<xsd-config>>.
To create new XML configuration extensions:
. <<xsd-custom-schema,Author>> an XML schema to describe your custom element(s).
. <<xsd-custom-namespacehandler,Code>> a custom `NamespaceHandler` implementation.
. <<xsd-custom-parser,Code>> one or more `BeanDefinitionParser` implementations
. <<xsd-custom-schema, Author>> an XML schema to describe your custom element(s).
. <<xsd-custom-namespacehandler, Code>> a custom `NamespaceHandler` implementation.
. <<xsd-custom-parser, Code>> one or more `BeanDefinitionParser` implementations
(this is where the real work is done).
. <<xsd-custom-registration,Register>> your new artifacts with Spring.
. <<xsd-custom-registration, Register>> your new artifacts with Spring.
For a unified example, we create an
XML extension (a custom XML element) that lets us configure objects of the type
@ -801,7 +788,7 @@ The `NamespaceHandler` interface features three methods: @@ -801,7 +788,7 @@ The `NamespaceHandler` interface features three methods:
* `BeanDefinitionHolder decorate(Node, BeanDefinitionHolder, ParserContext)`: Called
when Spring encounters an attribute or nested element of a different namespace.
The decoration of one or more bean definitions is used (for example) with the
<<core.adoc#beans-factory-scopes,scopes that Spring supports>>.
<<core.adoc#beans-factory-scopes, scopes that Spring supports>>.
We start by highlighting a simple example, without using decoration, after which
we show decoration in a somewhat more advanced example.
@ -889,7 +876,6 @@ the basic grunt work of creating a single `BeanDefinition`. @@ -889,7 +876,6 @@ 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
is the extraction and setting of the bean definition's unique identifier.
@ -898,6 +884,7 @@ is the extraction and setting of the bean definition's unique identifier. @@ -898,6 +884,7 @@ is the extraction and setting of the bean definition's unique identifier.
[[xsd-custom-registration]]
=== Registering the Handler and the Schema
The coding is finished. All that remains to be done is to make the Spring XML
parsing infrastructure aware of our custom element. We do so by registering our custom
`namespaceHandler` and custom XSD file in two special-purpose properties files. These
@ -907,7 +894,6 @@ XML parsing infrastructure automatically picks up your new extension by consumin @@ -907,7 +894,6 @@ XML parsing infrastructure automatically picks up your new extension by consumin
these special properties files, the formats of which are detailed in the next two sections.
[[xsd-custom-registration-spring-handlers]]
==== Writing `META-INF/spring.handlers`
@ -928,7 +914,6 @@ namespace extension and needs to exactly match exactly the value of the `targetN @@ -928,7 +914,6 @@ namespace extension and needs to exactly match exactly the value of the `targetN
attribute, as specified in your custom XSD schema.
[[xsd-custom-registration-spring-schemas]]
==== Writing 'META-INF/spring.schemas'
@ -995,7 +980,6 @@ in a Spring XML configuration file: @@ -995,7 +980,6 @@ in a Spring XML configuration file:
This section presents some more detailed examples of custom XML extensions.
[[xsd-custom-custom-nested]]
==== Nesting Custom Elements within Custom Elements
@ -1060,7 +1044,6 @@ The following listing shows the `Component` class: @@ -1060,7 +1044,6 @@ The following listing shows the `Component` class:
public void setName(String name) {
this.name = name;
}
}
----
@ -1068,7 +1051,6 @@ The typical solution to this issue is to create a custom `FactoryBean` that expo @@ -1068,7 +1051,6 @@ The typical solution to this issue is to create a custom `FactoryBean` that expo
setter property for the `components` property. The following listing shows such a custom
`FactoryBean`:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@ -1107,15 +1089,14 @@ setter property for the `components` property. The following listing shows such @@ -1107,15 +1089,14 @@ setter property for the `components` property. The following listing shows such
public boolean isSingleton() {
return true;
}
}
----
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
this Spring plumbing. If we stick to <<xsd-custom-introduction,the steps described
previously>>, we start off by creating the XSD schema to define the structure of our
custom tag, as the following listing shows:
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 this Spring plumbing.
If we stick to <<xsd-custom-introduction, the steps described previously>>, 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"]
@ -1141,7 +1122,8 @@ custom tag, as the following listing shows: @@ -1141,7 +1122,8 @@ custom tag, as the following listing shows:
</xsd:schema>
----
Again following <<xsd-custom-introduction,the process described earlier>>, we then create a custom `NamespaceHandler`:
Again following <<xsd-custom-introduction, the process described earlier>>,
we then create a custom `NamespaceHandler`:
[source,java,indent=0]
[subs="verbatim,quotes"]
@ -1155,13 +1137,12 @@ Again following <<xsd-custom-introduction,the process described earlier>>, we th @@ -1155,13 +1137,12 @@ Again following <<xsd-custom-introduction,the process described earlier>>, we th
public void init() {
registerBeanDefinitionParser("component", new ComponentBeanDefinitionParser());
}
}
----
Next up is the custom `BeanDefinitionParser`. Remember that we are creating
`BeanDefinition` that describes a `ComponentFactoryBean`. The following listing shows our
custom `BeanDefinitionParser`:
a `BeanDefinition` that describes a `ComponentFactoryBean`. The following
listing shows our custom `BeanDefinitionParser` implementation:
[source,java,indent=0]
[subs="verbatim,quotes"]
@ -1210,7 +1191,6 @@ custom `BeanDefinitionParser`: @@ -1210,7 +1191,6 @@ custom `BeanDefinitionParser`:
}
factory.addPropertyValue("children", children);
}
}
----
@ -1232,21 +1212,20 @@ http\://www.foo.com/schema/component/component.xsd=com/foo/component.xsd @@ -1232,21 +1212,20 @@ http\://www.foo.com/schema/component/component.xsd=com/foo/component.xsd
----
[[xsd-custom-custom-just-attributes]]
==== Custom Attributes on "`Normal`" Elements
Writing your own custom parser and the associated artifacts is not hard. However, it is sometimes
not the right thing to do. Consider a scenario where you need to add metadata to
already existing bean definitions. In this case, you certainly do not want to have to
write your own entire custom extension. Rather, you merely want to add an
additional attribute to the existing bean definition element.
Writing your own custom parser and the associated artifacts is not hard. However,
it is sometimes not the right thing to do. Consider a scenario where you need to
add metadata to already existing bean definitions. In this case, you certainly
do not want to have to write your own entire custom extension. Rather, you merely
want to add an additional attribute to the existing bean definition element.
By way of another example, suppose that you define a bean
definition for a service object that (unknown to it) accesses a clustered
http://jcp.org/en/jsr/detail?id=107[JCache], and you want to ensure that the named
JCache instance is eagerly started within the surrounding cluster. The following
listing shows such a definition:
By way of another example, suppose that you define a bean definition for a
service object that (unknown to it) accesses a clustered
http://jcp.org/en/jsr/detail?id=107[JCache], and you want to ensure that the
named JCache instance is eagerly started within the surrounding cluster.
The following listing shows such a definition:
[source,xml,indent=0]
[subs="verbatim,quotes"]
@ -1279,12 +1258,11 @@ JCache-initializing `BeanDefinition`. The following listing shows our `JCacheIni @@ -1279,12 +1258,11 @@ JCache-initializing `BeanDefinition`. The following listing shows our `JCacheIni
public void initialize() {
// lots of JCache API calls to initialize the named cache...
}
}
----
Now we can move onto the custom extension. First, we need to author the XSD schema that describes the
custom attribute, as follows:
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"]
@ -1320,9 +1298,9 @@ Next, we need to create the associated `NamespaceHandler`, as follows: @@ -1320,9 +1298,9 @@ 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`:
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` implementation:
[source,java,indent=0]
[subs="verbatim,quotes"]
@ -1376,7 +1354,6 @@ The following listing shows our `BeanDefinitionDecorator`: @@ -1376,7 +1354,6 @@ The following listing shows our `BeanDefinitionDecorator`:
}
return beanName;
}
}
----

138
src/docs/asciidoc/core/core-beans.adoc

@ -104,13 +104,13 @@ Spring IoC container. @@ -104,13 +104,13 @@ Spring IoC container.
NOTE: XML-based metadata is not the only allowed form of configuration metadata.
The Spring IoC container itself is totally decoupled from the format in which this
configuration metadata is actually written. These days, many developers choose
<<beans-java,Java-based configuration>> for their Spring applications.
<<beans-java, Java-based configuration>> for their Spring applications.
For information about using other forms of metadata with the Spring container, see:
* <<beans-annotation-config,Annotation-based configuration>>: Spring 2.5 introduced
support for annotation-based configuration metadata.
* <<beans-java,Java-based configuration>>: Starting with Spring 3.0, many features
* <<beans-java, Java-based configuration>>: Starting with Spring 3.0, many features
provided by the Spring JavaConfig project became part of the core Spring Framework.
Thus, you can define beans external to your application classes by using Java rather
than XML files. To use these new features, see the
@ -257,7 +257,7 @@ XML configuration file represents a logical layer or module in your architecture @@ -257,7 +257,7 @@ XML configuration file represents a logical layer or module in your architecture
You can use the application context constructor to load bean definitions from all these
XML fragments. This constructor takes multiple `Resource` locations, as was shown in the
<<beans-factory-instantiation,previous section>>. Alternatively, use one or more
<<beans-factory-instantiation, previous section>>. Alternatively, use one or more
occurrences of the `<import/>` element to load bean definitions from another file or
files. The following example shows how to do so:
@ -974,8 +974,8 @@ example shows: @@ -974,8 +974,8 @@ 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.
If you cannot or do not want to compile your code with the debug flag, you can use
http://download.oracle.com/javase/6/docs/api/java/beans/ConstructorProperties.html[@ConstructorProperties]
If you cannot or do not want to compile your code with the debug flag, you can use the
http://download.oracle.com/javase/8/docs/api/java/beans/ConstructorProperties.html[@ConstructorProperties]
JDK annotation to explicitly name your constructor arguments. The sample class would
then have to look as follows:
@ -1042,7 +1042,7 @@ load an entire Spring IoC container instance. @@ -1042,7 +1042,7 @@ load an entire Spring IoC container instance.
****
Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to
use constructors for mandatory dependencies and setter methods or configuration methods
for optional dependencies. Note that use of the <<beans-required-annotation,@Required>>
for optional dependencies. Note that use of the <<beans-required-annotation, @Required>>
annotation on a setter method can be used to make the property be a required dependency;
however, constructor injection with programmatic validation of arguments is preferable.
@ -1135,7 +1135,7 @@ to being injected into the dependent bean. This means that, if bean A has a depe @@ -1135,7 +1135,7 @@ to being injected into the dependent bean. This means that, if bean A has a depe
bean B, the Spring IoC container completely configures bean B prior to invoking the
setter method on bean A. In other words, the bean is instantiated (if it is not a
pre-instantiated singleton), its dependencies are set, and the relevant lifecycle
methods (such as a <<beans-factory-lifecycle-initializingbean,configured init method>>
methods (such as a <<beans-factory-lifecycle-initializingbean, configured init method>>
or the <<beans-factory-lifecycle-initializingbean,InitializingBean callback method>>)
are invoked.
@ -1292,7 +1292,7 @@ do not discuss those details here. @@ -1292,7 +1292,7 @@ do not discuss those details here.
[[beans-factory-properties-detailed]]
=== Dependencies and Configuration in Detail
As mentioned in the <<beans-factory-collaborators,previous section>>, you can define bean
As mentioned in the <<beans-factory-collaborators, previous section>>, you can define bean
properties and constructor arguments as references to other managed beans (collaborators)
or as values defined inline. Spring's XML-based configuration metadata supports
sub-element types within its `<property/>` and `<constructor-arg/>` elements for this
@ -2077,11 +2077,11 @@ In the latter scenario, you have several options: @@ -2077,11 +2077,11 @@ In the latter scenario, you have several options:
* Abandon autowiring in favor of explicit wiring.
* Avoid autowiring for a bean definition by setting its `autowire-candidate` attributes
to `false`, as described in the <<beans-factory-autowire-candidate,next section>>.
to `false`, as described in the <<beans-factory-autowire-candidate, next section>>.
* Designate a single bean definition as the primary candidate by setting the
`primary` attribute of its `<bean/>` element to `true`.
* Implement the more fine-grained control available
with annotation-based configuration, as described in <<beans-annotation-config>>.
* Implement the more fine-grained control available with annotation-based configuration,
as described in <<beans-annotation-config>>.
@ -2184,7 +2184,7 @@ https://spring.io/blog/2004/08/06/method-injection/[this blog entry]. @@ -2184,7 +2184,7 @@ https://spring.io/blog/2004/08/06/method-injection/[this blog entry].
Lookup method injection is the ability of the container to override methods on
container-managed beans and return the lookup result for another named bean in the
container. The lookup typically involves a prototype bean, as in the scenario described
in <<beans-factory-method-injection,the preceding section>>. The Spring Framework
in <<beans-factory-method-injection, the preceding section>>. The Spring Framework
implements this method injection by using bytecode generation from the CGLIB library to
dynamically generate a subclass that overrides the method.
@ -3326,7 +3326,7 @@ configured with a different method name, then each configured method is executed @@ -3326,7 +3326,7 @@ configured with a different method name, then each configured method is executed
order listed after this note. However, if the same method name is configured -- for example,
`init()` for an initialization method -- for more than one of these lifecycle mechanisms,
that method is executed once, as explained in the
<<beans-factory-lifecycle-default-init-destroy-methods,preceding section>>.
<<beans-factory-lifecycle-default-init-destroy-methods, preceding section>>.
Multiple lifecycle mechanisms configured for the same bean, with different
initialization methods, are called as follows:
@ -3575,7 +3575,7 @@ init-method. @@ -3575,7 +3575,7 @@ init-method.
[[aware-list]]
=== Other `Aware` Interfaces
Besides `ApplicationContextAware` and `BeanNameAware` (discussed <<beans-factory-aware,earlier>>),
Besides `ApplicationContextAware` and `BeanNameAware` (discussed <<beans-factory-aware, earlier>>),
Spring offers a wide range of `Aware` callback interfaces that let beans indicate to the container
that they require a certain infrastructure dependency. As a general rule, the name indicates the
dependency type. The following table summarizes the most important `Aware` interfaces:
@ -3680,7 +3680,6 @@ to do so: @@ -3680,7 +3680,6 @@ 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
compatible with the parent (that is, it must accept the parent's property values).
@ -4207,7 +4206,7 @@ while others argue that annotated classes are no longer POJOs and, furthermore, @@ -4207,7 +4206,7 @@ while others argue that annotated classes are no longer POJOs and, furthermore,
configuration becomes decentralized and harder to control.
No matter the choice, Spring can accommodate both styles and even mix them together.
It is worth pointing out that through its <<beans-java,JavaConfig>> option, Spring lets
It is worth pointing out that through its <<beans-java, JavaConfig>> option, Spring lets
annotations be used in a non-invasive way, without touching the target components
source code and that, in terms of tooling, all configuration styles are supported by the
https://spring.io/tools/sts[Spring Tool Suite].
@ -4588,7 +4587,7 @@ an `ApplicationContext` object: @@ -4588,7 +4587,7 @@ an `ApplicationContext` object:
[NOTE]
====
The `@Autowired`, `@Inject`, `@Resource`, and `@Value` annotations are handled by Spring
The `@Autowired`, `@Inject`, `@Value`, and `@Resource` annotations are handled by Spring
`BeanPostProcessor` implementations. This means that you cannot apply these annotations
within your own `BeanPostProcessor` or `BeanFactoryPostProcessor` types (if any).
These types must be 'wired up' explicitly by using XML or a Spring `@Bean` method.
@ -5327,9 +5326,9 @@ supported as a marker for automatic exception translation in your persistence la @@ -5327,9 +5326,9 @@ supported as a marker for automatic exception translation in your persistence la
=== Using Meta-annotations and Composed Annotations
Many of the annotations provided by Spring can be used as meta-annotations in your
own code. A meta-annotation is an annotation that can be applied to another
annotation. For example, the `@Service` annotation mentioned <<beans-stereotype-annotations,earlier>> is meta-annotated with
`@Component`, as the following example shows:
own code. A meta-annotation is an annotation that can be applied to another annotation.
For example, the `@Service` annotation mentioned <<beans-stereotype-annotations, earlier>>
is meta-annotated with `@Component`, as the following example shows:
[source,java,indent=0]
[subs="verbatim,quotes"]
@ -5482,16 +5481,16 @@ TIP: The use of `<context:component-scan>` implicitly enables the functionality @@ -5482,16 +5481,16 @@ TIP: The use of `<context:component-scan>` implicitly enables the functionality
====
The scanning of classpath packages requires the presence of corresponding directory
entries in the classpath. When you build JARs with Ant, make sure that you do not
activate the files-only switch of the JAR task. Also, classpath directories may not
be exposed based on security policies in some environments -- for example, standalone apps on
activate the files-only switch of the JAR task. Also, classpath directories may not be
exposed based on security policies in some environments -- for example, standalone apps on
JDK 1.7.0_45 and higher (which requires 'Trusted-Library' setup in your manifests -- see
http://stackoverflow.com/questions/19394570/java-jre-7u45-breaks-classloader-getresources).
On JDK 9's module path (Jigsaw), Spring's classpath scanning generally works as expected.
However, make sure that your component classes are exported in your `module-info`
descriptors. If you expect Spring to invoke non-public members of your classes, make
sure that they are 'opened' (that is, that they use an `opens` declaration instead of an `exports`
declaration in your `module-info` descriptor).
sure that they are 'opened' (that is, that they use an `opens` declaration instead of an
`exports` declaration in your `module-info` descriptor).
====
Furthermore, the `AutowiredAnnotationBeanPostProcessor` and
@ -6466,7 +6465,7 @@ following example shows: @@ -6466,7 +6465,7 @@ following example shows:
}
----
NOTE: Remember that `@Configuration` classes are <<beans-meta-annotations,meta-annotated>>
NOTE: Remember that `@Configuration` classes are <<beans-meta-annotations, meta-annotated>>
with `@Component`, so they are candidates for component-scanning. In the preceding example,
assuming that `AppConfig` is declared within the `com.acme` package (or any package
underneath), it is picked up during the call to `scan()`. Upon `refresh()`, all its `@Bean`
@ -6544,8 +6543,8 @@ init-param): @@ -6544,8 +6543,8 @@ init-param):
`@Bean` is a method-level annotation and a direct analog of the XML `<bean/>` element.
The annotation supports some of the attributes offered by `<bean/>`, such as:
* <<beans-factory-lifecycle-initializingbean,init-method>>
* <<beans-factory-lifecycle-disposablebean,destroy-method>>
* <<beans-factory-lifecycle-initializingbean, init-method>>
* <<beans-factory-lifecycle-disposablebean, destroy-method>>
* <<beans-factory-autowire,autowiring>>
* `name`.
@ -6647,7 +6646,7 @@ parameter, as the following example shows: @@ -6647,7 +6646,7 @@ parameter, as the following example shows:
----
The resolution mechanism is pretty much identical to constructor-based dependency
injection. See <<beans-constructor-injection,the relevant section>> for more details.
injection. See <<beans-constructor-injection, the relevant section>> for more details.
[[beans-java-lifecycle-callbacks]]
@ -6655,17 +6654,17 @@ injection. See <<beans-constructor-injection,the relevant section>> for more det @@ -6655,17 +6654,17 @@ injection. See <<beans-constructor-injection,the relevant section>> for more det
Any classes defined with the `@Bean` annotation support the regular lifecycle callbacks
and can use the `@PostConstruct` and `@PreDestroy` annotations from JSR-250. See
<<beans-postconstruct-and-predestroy-annotations,JSR-250 annotations>> for further
<<beans-postconstruct-and-predestroy-annotations, JSR-250 annotations>> for further
details.
The regular Spring <<beans-factory-nature,lifecycle>> callbacks are fully supported as
The regular Spring <<beans-factory-nature, lifecycle>> callbacks are fully supported as
well. If a bean implements `InitializingBean`, `DisposableBean`, or `Lifecycle`, their
respective methods are called by the container.
The standard set of `*Aware` interfaces (such as <<beans-beanfactory,BeanFactoryAware>>,
<<beans-factory-aware,BeanNameAware>>,
<<context-functionality-messagesource,MessageSourceAware>>,
<<beans-factory-aware,ApplicationContextAware>>, and so on) are also fully supported.
The standard set of `*Aware` interfaces (such as <<beans-beanfactory, BeanFactoryAware>>,
<<beans-factory-aware, BeanNameAware>>,
<<context-functionality-messagesource, MessageSourceAware>>,
<<beans-factory-aware, ApplicationContextAware>>, and so on) are also fully supported.
The `@Bean` annotation supports specifying arbitrary initialization and destruction
callback methods, much like Spring XML's `init-method` and `destroy-method` attributes
@ -6769,7 +6768,7 @@ Spring includes the `@Scope` annotation so that you can specify the scope of a b @@ -6769,7 +6768,7 @@ Spring includes the `@Scope` annotation so that you can specify the scope of a b
You can specify that your beans defined with the `@Bean` annotation should have a
specific scope. You can use any of the standard scopes specified in the
<<beans-factory-scopes,Bean Scopes>> section.
<<beans-factory-scopes, Bean Scopes>> section.
The default scope is `singleton`, but you can override this with the `@Scope` annotation,
as the following example shows:
@ -6792,14 +6791,15 @@ as the following example shows: @@ -6792,14 +6791,15 @@ as the following example shows:
===== `@Scope` and `scoped-proxy`
Spring offers a convenient way of working with scoped dependencies through
<<beans-factory-scopes-other-injection,scoped proxies>>. The easiest way to create such
a proxy when using the XML configuration is the `<aop:scoped-proxy/>` element.
Configuring your beans in Java with a `@Scope` annotation offers equivalent support with
the `proxyMode` attribute. The default is no proxy (`ScopedProxyMode.NO`), but you can
specify `ScopedProxyMode.TARGET_CLASS` or `ScopedProxyMode.INTERFACES`.
<<beans-factory-scopes-other-injection, scoped proxies>>. The easiest way to create
such a proxy when using the XML configuration is the `<aop:scoped-proxy/>` element.
Configuring your beans in Java with a `@Scope` annotation offers equivalent support
with the `proxyMode` attribute. The default is no proxy (`ScopedProxyMode.NO`),
but you can specify `ScopedProxyMode.TARGET_CLASS` or `ScopedProxyMode.INTERFACES`.
If you port the scoped proxy example from the XML reference documentation (see
<<beans-factory-scopes-other-injection,scoped proxies>>) to our `@Bean` using Java, it resembles the following:
<<beans-factory-scopes-other-injection, scoped proxies>>) to our `@Bean` using Java,
it resembles the following:
[source,java,indent=0]
[subs="verbatim,quotes"]
@ -6935,7 +6935,7 @@ by using plain `@Component` classes. @@ -6935,7 +6935,7 @@ by using plain `@Component` classes.
[[beans-java-method-injection]]
==== Lookup Method Injection
As noted earlier, <<beans-factory-method-injection,lookup method injection>> is an
As noted earlier, <<beans-factory-method-injection, lookup method injection>> is an
advanced feature that you should use rarely. It is useful in cases where a
singleton-scoped bean has a dependency on a prototype-scoped bean. Using Java for this
type of configuration provides a natural means for implementing this pattern. The
@ -7123,7 +7123,7 @@ issue, because no compiler is involved, and you can declare @@ -7123,7 +7123,7 @@ issue, because no compiler is involved, and you can declare
When using `@Configuration` classes, the Java compiler places constraints on
the configuration model, in that references to other beans must be valid Java syntax.
Fortunately, solving this problem is simple. As <<beans-java-dependencies,we already discussed>>,
Fortunately, solving this problem is simple. As <<beans-java-dependencies, we already discussed>>,
a `@Bean` method can have an arbitrary number of parameters that describe the bean
dependencies. Consider the following more real-world scenario with several `@Configuration`
classes, each depending on beans declared in the others:
@ -7581,8 +7581,8 @@ jdbc.password= @@ -7581,8 +7581,8 @@ jdbc.password=
The {api-spring-framework}/core/env/Environment.html[`Environment`] interface
is an abstraction integrated in the container that models two key
aspects of the application environment: <<beans-definition-profiles,profiles>>
and <<beans-property-source-abstraction,properties>>.
aspects of the application environment: <<beans-definition-profiles, profiles>>
and <<beans-property-source-abstraction, properties>>.
A profile is a named, logical group of bean definitions to be registered with the
container only if the given profile is active. Beans may be assigned to a profile
@ -7719,7 +7719,7 @@ NOTE: You cannot mix the `&` and `|` operators without using parentheses. For ex @@ -7719,7 +7719,7 @@ NOTE: You cannot mix the `&` and `|` operators without using parentheses. For ex
`production & us-east | eu-central` is not a valid expression. It must be expressed as
`production & (us-east | eu-central)`.
You can use `@Profile` as a <<beans-meta-annotations,meta-annotation>> for the purpose
You can use `@Profile` as a <<beans-meta-annotations, meta-annotation>> for the purpose
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")`:
@ -7915,9 +7915,9 @@ In addition, you can also declaratively activate profiles through the @@ -7915,9 +7915,9 @@ In addition, you can also declaratively activate profiles through the
`spring.profiles.active` property, which may be specified through system environment
variables, JVM system properties, servlet context parameters in `web.xml`, or even as an
entry in JNDI (see <<beans-property-source-abstraction>>). In integration tests, active
profiles can be declared by using the `@ActiveProfiles` annotation in the `spring-test` module
(see <<testing.adoc#testcontext-ctx-management-env-profiles,
Context configuration with environment profiles>>).
profiles can be declared by using the `@ActiveProfiles` annotation in the `spring-test`
module (see <<testing.adoc#testcontext-ctx-management-env-profiles,
context configuration with environment profiles>>).
Note that profiles are not an "`either-or`" proposition. You can activate multiple
profiles at once. Programmatically, you can provide multiple profile names to the
@ -8169,9 +8169,10 @@ Alternatively, for XML configuration, you can use the `context:load-time-weaver` @@ -8169,9 +8169,10 @@ 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
weaver instance. This is particularly useful in combination with
<<data-access.adoc#orm-jpa,Spring's JPA support>> where load-time weaving may be necessary
for JPA class transformation.
Consult the {api-spring-framework}/orm/jpa/LocalContainerEntityManagerFactoryBean.html[`LocalContainerEntityManagerFactoryBean`]
<<data-access.adoc#orm-jpa, Spring's JPA support>> where load-time weaving may be
necessary for JPA class transformation.
Consult the
{api-spring-framework}/orm/jpa/LocalContainerEntityManagerFactoryBean.html[`LocalContainerEntityManagerFactoryBean`]
javadoc for more detail. For more on AspectJ load-time weaving, see <<aop-aj-ltw>>.
@ -8180,7 +8181,7 @@ javadoc for more detail. For more on AspectJ load-time weaving, see <<aop-aj-ltw @@ -8180,7 +8181,7 @@ javadoc for more detail. For more on AspectJ load-time weaving, see <<aop-aj-ltw
[[context-introduction]]
== Additional Capabilities of the `ApplicationContext`
As discussed in the <<beans,chapter introduction>>, the `org.springframework.beans.factory`
As discussed in the <<beans, chapter introduction>>, the `org.springframework.beans.factory`
package provides basic functionality for managing and manipulating beans, including in a
programmatic way. The `org.springframework.context` package adds the
{api-spring-framework}/context/ApplicationContext.html[`ApplicationContext`]
@ -8416,7 +8417,7 @@ class and the `ApplicationListener` interface. If a bean that implements the @@ -8416,7 +8417,7 @@ class and the `ApplicationListener` interface. If a bean that implements the
Essentially, this is the standard Observer design pattern.
TIP: As of Spring 4.2, the event infrastructure has been significantly improved and offers
an <<context-functionality-events-annotation,annotation-based model>> as well as the
an <<context-functionality-events-annotation, annotation-based model>> as well as the
ability to publish any arbitrary event (that is, an object that does not necessarily
extend from `ApplicationEvent`). When such an object is published, we wrap it in an
event for you.
@ -8640,12 +8641,12 @@ following example shows how to do so: @@ -8640,12 +8641,12 @@ 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 <<expressions,`SpEL` expression>> , which should match to actually
invoke the method for a particular event.
It is also possible to add additional runtime filtering by using the `condition` attribute
of the annotation that defines a <<expressions, `SpEL` expression>> , which should match
to actually 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`:
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"]
@ -8699,8 +8700,8 @@ method signature to return the event that should be published, as the following @@ -8699,8 +8700,8 @@ method signature to return the event that should be published, as the following
}
----
NOTE: This feature is not supported for <<context-functionality-events-async,asynchronous
listeners>>.
NOTE: This feature is not supported for
<<context-functionality-events-async, asynchronous listeners>>.
This new method publishes a new `ListUpdateEvent` for every `BlackListEvent` handled by the
method above. If you need to publish several events, you can return a `Collection` of events
@ -8711,8 +8712,8 @@ instead. @@ -8711,8 +8712,8 @@ instead.
==== Asynchronous Listeners
If you want a particular listener to process events asynchronously, you can reuse the
<<integration.adoc#scheduling-annotation-support-async,regular `@Async` support>>. The
following example shows how to do so:
<<integration.adoc#scheduling-annotation-support-async, regular `@Async` support>>.
The following example shows how to do so:
[source,java,indent=0]
[subs="verbatim,quotes"]
@ -8801,9 +8802,8 @@ an event. @@ -8801,9 +8802,8 @@ an event.
[[context-functionality-resources]]
=== Convenient Access to Low-level Resources
For optimal usage and understanding of application contexts, you should
familiarize yourself with Spring's `Resource` abstraction, as described in
<<resources>>.
For optimal usage and understanding of application contexts, you should familiarize
yourself with Spring's `Resource` abstraction, as described in <<resources>>.
An application context is a `ResourceLoader`, which can be used to load `Resource` objects.
A `Resource` is essentially a more feature rich version of the JDK `java.net.URL` class.
@ -8957,11 +8957,11 @@ by convention (that is, by bean name or by bean type -- in particular, post-proc @@ -8957,11 +8957,11 @@ by convention (that is, by bean name or by bean type -- in particular, post-proc
while a plain `DefaultListableBeanFactory` is agnostic about any special beans.
For many extended container features, such as annotation processing and AOP proxying,
the <<beans-factory-extension-bpp,`BeanPostProcessor` extension point>> is essential.
the <<beans-factory-extension-bpp, `BeanPostProcessor` extension point>> is essential.
If you use only a plain `DefaultListableBeanFactory`, such post-processors do not
get detected and activated by default. This situation could be confusing, because
nothing is actually wrong with your bean configuration. Rather, in such a scenario, the
container needs to be fully bootstrapped through additional setup.
nothing is actually wrong with your bean configuration. Rather, in such a scenario,
the container needs to be fully bootstrapped through additional setup.
The following table lists features provided by the `BeanFactory` and
`ApplicationContext` interfaces and implementations.

7
src/docs/asciidoc/core/core-databuffer-codec.adoc

@ -10,7 +10,7 @@ APIs as follows: @@ -10,7 +10,7 @@ APIs as follows:
* <<databuffers-factory>> abstracts the creation of a data buffer.
* <<databuffers-buffer>> represents a byte buffer, which may be
<<databuffers-buffer-pooled,pooled>>.
<<databuffers-buffer-pooled, pooled>>.
* <<databuffers-utils>> offers utility methods for data buffers.
* <<Codecs>> decode or encode streams data buffer streams into higher level objects.
@ -93,7 +93,6 @@ composite buffers, if that's supported by the underlying byte buffer API. @@ -93,7 +93,6 @@ composite buffers, if that's supported by the underlying byte buffer API.
[[codecs]]
== Codecs
@ -105,7 +104,7 @@ The `org.springframework.core.codec` package provides the following strategy int @@ -105,7 +104,7 @@ The `org.springframework.core.codec` package provides the following strategy int
The `spring-core` module provides `byte[]`, `ByteBuffer`, `DataBuffer`, `Resource`, and
`String` encoder and decoder implementations. The `spring-web` module adds Jackson JSON,
Jackson Smile, JAXB2, Protocol Buffers and other encoders and decoders. See
<<web-reactive.adoc#webflux-codecs,Codecs>> in the WebFlux section.
<<web-reactive.adoc#webflux-codecs, Codecs>> in the WebFlux section.
@ -114,7 +113,7 @@ Jackson Smile, JAXB2, Protocol Buffers and other encoders and decoders. See @@ -114,7 +113,7 @@ Jackson Smile, JAXB2, Protocol Buffers and other encoders and decoders. See
== Using `DataBuffer`
When working with data buffers, special care must be taken to ensure buffers are released
since they may be <<databuffers-buffer-pooled,pooled>>. We'll use codecs to illustrate
since they may be <<databuffers-buffer-pooled, pooled>>. We'll use codecs to illustrate
how that works but the concepts apply more generally. Let's see what codecs must do
internally to manage data buffers.

31
src/docs/asciidoc/core/core-expressions.adoc

@ -10,8 +10,8 @@ While there are several other Java expression languages available -- OGNL, MVEL, @@ -10,8 +10,8 @@ While there are several other Java expression languages available -- OGNL, MVEL,
EL, to name a few -- the Spring Expression Language was created to provide the Spring
community with a single well supported expression language that can be used across all
the products in the Spring portfolio. Its language features are driven by the
requirements of the projects in the Spring portfolio, including tooling requirements for
code completion support within the Eclipse-based Spring Tool Suite. That said,
requirements of the projects in the Spring portfolio, including tooling requirements
for code completion support within the Eclipse-based Spring Tool Suite. That said,
SpEL is based on a technology-agnostic API that lets other expression language
implementations be integrated, should the need arise.
@ -20,14 +20,14 @@ portfolio, it is not directly tied to Spring and can be used independently. To @@ -20,14 +20,14 @@ portfolio, it is not directly tied to Spring and can be used independently. To
be self contained, many of the examples in this chapter use SpEL as if it were an
independent expression language. This requires creating a few bootstrapping
infrastructure classes, such as the parser. Most Spring users need not deal with
this infrastructure and can, instead, author only expression strings for evaluation. An
example of this typical use is the integration of SpEL into creating XML or annotation-based
bean definitions, as shown in <<expressions-beandef,Expression support
for defining bean definitions>>.
this infrastructure and can, instead, author only expression strings for evaluation.
An example of this typical use is the integration of SpEL into creating XML or
annotation-based bean definitions, as shown in
<<expressions-beandef, Expression support for defining bean definitions>>.
This chapter covers the features of the expression language, its API, and its language
syntax. In several places, `Inventor` and `Society` classes are used as the
target objects for expression evaluation. These class declarations and the data used to
syntax. In several places, `Inventor` and `Society` classes are used as the target
objects for expression evaluation. These class declarations and the data used to
populate them are listed at the end of the chapter.
The expression language supports the following functionality:
@ -60,7 +60,7 @@ The expression language supports the following functionality: @@ -60,7 +60,7 @@ The expression language supports the following functionality:
This section introduces the simple use of SpEL interfaces and its expression language.
The complete language reference can be found in
<<expressions-language-ref,Language Reference>>.
<<expressions-language-ref, Language Reference>>.
The following code introduces the SpEL API to evaluate the literal string expression,
`Hello World`.
@ -319,13 +319,14 @@ interpreter and only 3ms using the compiled version of the expression. @@ -319,13 +319,14 @@ interpreter and only 3ms using the compiled version of the expression.
[[expressions-compiler-configuration]]
==== Compiler Configuration
The compiler is not turned on by default, but you can turn it on in either of two different ways.
You can turn it on by using the parser configuration process (<<expressions-parser-configuration,discussed earlier>>)
or by using a system property when SpEL usage is embedded inside another component. This section
The compiler is not turned on by default, but you can turn it on in either of two
different ways. You can turn it on by using the parser configuration process
(<<expressions-parser-configuration, discussed earlier>>) or by using a system
property when SpEL usage is embedded inside another component. This section
discusses both of these options.
The compiler can operate in one of three modes, which are captured
in the `org.springframework.expression.spel.SpelCompilerMode` enum. The modes are as follows:
The compiler can operate in one of three modes, which are captured in the
`org.springframework.expression.spel.SpelCompilerMode` enum. The modes are as follows:
* `OFF` (default): The compiler is switched off.
* `IMMEDIATE`: In immediate mode, the expressions are compiled as soon as possible. This
@ -612,7 +613,7 @@ By default, real numbers are parsed by using Double.parseDouble(). @@ -612,7 +613,7 @@ By default, real numbers are parsed by using Double.parseDouble().
Navigating with property references is easy. To do so, use a period to indicate a nested
property value. The instances of the `Inventor` class, `pupin` and `tesla`, were populated with
data listed in the <<expressions-example-classes,Classes used in the examples>> section.
data listed in the <<expressions-example-classes, Classes used in the examples>> section.
To navigate "`down`" and get Tesla's year of birth and Pupin's city of birth, we use the following
expressions:

64
src/docs/asciidoc/core/core-null-safety.adoc

@ -1,29 +1,31 @@ @@ -1,29 +1,31 @@
[[null-safety]]
[-[null-safety]]
= Null-safety
Although Java does not let you express null-safety with its type system, Spring Framework
now provides the following annotations in the `org.springframework.lang` package to let you declare
nullability of APIs and fields:
Although Java does not let you express null-safety with its type system, the Spring Framework
now provides the following annotations in the `org.springframework.lang` package to let you
declare nullability of APIs and fields:
* {api-spring-framework}/lang/NonNull.html[`@NonNull`]: Annotation to indicate that a specific parameter,
return value, or field cannot be `null` (not needed on parameter and return value
where `@NonNullApi` and `@NonNullFields` apply) .
* {api-spring-framework}/lang/Nullable.html[`@Nullable`]: Annotation to indicate that a specific
parameter, return value, or field can be `null`.
* {api-spring-framework}/lang/Nullable.html[`@Nullable`]: Annotation to indicate that a
specific parameter, return value, or field can be `null`.
* {api-spring-framework}/lang/NonNull.html[`@NonNull`]: Annotation to indicate that a specific
parameter, return value, or field cannot be `null` (not needed on parameters / return values
and fields where `@NonNullApi` and `@NonNullFields` apply, respectively).
* {api-spring-framework}/lang/NonNullApi.html[`@NonNullApi`]: Annotation at the package level
that declares non-null as the default behavior for parameters and return values.
that declares non-null as the default semantics for parameters and return values.
* {api-spring-framework}/lang/NonNullFields.html[`@NonNullFields`]: Annotation at the package
level that declares non-null as the default behavior for fields.
level that declares non-null as the default semantics for fields.
Spring Framework leverages itself these annotations, but they can also be used in any Spring based
Java project to declare null-safe APIs and optionally null-safe fields. Generic type arguments,
varargs and array elements nullability are not supported yet, but should be in an upcoming
release, see https://jira.spring.io/browse/SPR-15942[SPR-15942] for up-to-date information.
Nullability declaration are expected to be fine-tuned between Spring Framework release,
including minor ones. Nullability of types used inside method bodies is outside of the
scope of this feature.
The Spring Framework itself leverages these annotations, but they can also be used in any
Spring-based Java project to declare null-safe APIs and optionally null-safe fields.
Generic type arguments, varargs and array elements nullability are not supported yet but
should be in an upcoming release, see https://jira.spring.io/browse/SPR-15942[SPR-15942]
for up-to-date information. Nullability declarations are expected to be fine-tuned between
Spring Framework releases, including minor ones. Nullability of types used inside method
bodies is outside of the scope of this feature.
NOTE: Libraries like Reactor or Spring Data provide null-safe APIs that use this feature.
NOTE: Other common libraries such as Reactor and Spring Data provide null-safe APIs that
use a similar nullability arrangement, delivering a consistent overall experience for
Spring application developers.
@ -32,25 +34,23 @@ NOTE: Libraries like Reactor or Spring Data provide null-safe APIs that use this @@ -32,25 +34,23 @@ NOTE: Libraries like Reactor or Spring Data provide null-safe APIs that use this
In addition to providing an explicit declaration for Spring Framework API nullability,
these annotations can be used by an IDE (such as IDEA or Eclipse) to provide useful
warnings related to null-safety in order to avoid `NullPointerException`
at runtime.
warnings related to null-safety in order to avoid `NullPointerException` at runtime.
They are also used to make Spring API null-safe in Kotlin projects, since Kotlin natively
supports https://kotlinlang.org/docs/reference/null-safety.html[null-safety]. More details
are available in the <<languages#kotlin-null-safety,Kotlin support documentation>>.
are available in the <<languages#kotlin-null-safety, Kotlin support documentation>>.
== JSR 305 meta-annotations
== JSR-305 meta-annotations
Spring annotations are meta-annotated with https://jcp.org/en/jsr/detail?id=305[JSR 305]
annotations (a dormant but widely spread JSR). JSR 305 meta-annotations let tooling vendors
like IDEA or Kotlin provide null-safety support in a generic way, without having to hard-code
support for Spring annotations.
It is not necessary nor recommended to add JSR 305 dependency in the project classpath to
take advantage of Spring null-safe API. Only projects such as
Spring-based libraries that use null-safety annotations in their codebase should add
`com.google.code.findbugs:jsr305:3.0.2` with `compileOnly` Gradle configuration or Maven
`provided` scope to avoid compile warnings.
annotations (a dormant but wide-spread JSR). JSR-305 meta-annotations let tooling vendors
like IDEA or Kotlin provide null-safety support in a generic way, without having to
hard-code support for Spring annotations.
It is not necessary nor recommended to add a JSR-305 dependency to the project classpath to
take advantage of Spring null-safe API. Only projects such as Spring-based libraries that use
null-safety annotations in their codebase should add `com.google.code.findbugs:jsr305:3.0.2`
with `compileOnly` Gradle configuration or Maven `provided` scope to avoid compile warnings.

8
src/docs/asciidoc/core/core-resources.adoc

@ -337,10 +337,10 @@ interface if that is all you need. The code would be coupled only to the resourc @@ -337,10 +337,10 @@ interface if that is all you need. The code would be coupled only to the resourc
interface (which can be considered a utility interface) and not to the whole Spring
`ApplicationContext` interface.
As of Spring 2.5, you can rely upon autowiring of the `ResourceLoader` as an alternative
to implementing the `ResourceLoaderAware` interface. The "`traditional`" `constructor` and
`byType` autowiring modes (as described in <<beans-factory-autowire>>) are now capable of
providing a dependency of type `ResourceLoader` for either a constructor argument or a
In application components, you may also rely upon autowiring of the `ResourceLoader` as
an alternative to implementing the `ResourceLoaderAware` interface. The "`traditional`"
`constructor` and `byType` autowiring modes (as described in <<beans-factory-autowire>>)
are capable of providing a `ResourceLoader` for either a constructor argument or a
setter method parameter, respectively. For more flexibility (including the ability to
autowire fields and multiple parameter methods), consider using the annotation-based
autowiring features. In that case, the `ResourceLoader` is autowired into a field,

88
src/docs/asciidoc/core/core-validation.adoc

@ -20,18 +20,19 @@ directly. Because this is reference documentation, however, we felt that some ex @@ -20,18 +20,19 @@ directly. Because this is reference documentation, however, we felt that some ex
might be in order. We explain the `BeanWrapper` in this chapter, since, if you are
going to use it at all, you are most likely do so when trying to bind data to objects.
Spring's `DataBinder` and the lower-level `BeanWrapper` both use `PropertyEditorSupport` implementations to parse
and format property values. The `PropertyEditor` and `PropertyEditorSupport` interfaces are part of the JavaBeans
specification and are also explained in this chapter. Spring 3 introduced a
`core.convert` package that provides a general type conversion facility, as well as a
higher-level "`format`" package for formatting UI field values. You can use these packages
as simpler alternatives to `PropertyEditorSupport` implementations. They are also discussed in this
chapter.
Spring's `DataBinder` and the lower-level `BeanWrapper` both use `PropertyEditorSupport`
implementations to parse and format property values. The `PropertyEditor` and
`PropertyEditorSupport` types are part of the JavaBeans specification and are also
explained in this chapter. Spring 3 introduced a `core.convert` package that provides a
general type conversion facility, as well as a higher-level "`format`" package for
formatting UI field values. You can use these packages as simpler alternatives to
`PropertyEditorSupport` implementations. They are also discussed in this chapter.
.JSR-303/JSR-349 Bean Validation
****
As of version 4.0, Spring Framework supports Bean Validation 1.0 (JSR-303) and Bean Validation 1.1
(JSR-349) for setup support and adapting them to Spring's `Validator` interface.
As of version 4.0, Spring Framework supports Bean Validation 1.0 (JSR-303) and
Bean Validation 1.1 (JSR-349) for setup support and adapting them to Spring's
`Validator` interface.
An application can choose to enable Bean Validation once globally, as described in
<<validation-beanvalidation>>, and use it exclusively for all validation needs.
@ -167,22 +168,21 @@ methods it offers can be found in the {api-spring-framework}validation/Errors.ht @@ -167,22 +168,21 @@ methods it offers can be found in the {api-spring-framework}validation/Errors.ht
[[validation-conversion]]
== Resolving Codes to Error Messages
We covered databinding and validation. This section covers outputting messages that correspond to
validation errors. In the example shown in the <<validator,preceding section>>,
we rejected the `name` and `age` fields. If we want to output the error
messages by using a `MessageSource`, we can do so using the error code we provide when
rejecting the field ('name' and 'age' in this case). When you call (either directly, or
indirectly, by using, for example, the `ValidationUtils` class) `rejectValue` or one of the
other `reject` methods from the `Errors` interface, the underlying implementation
not only registers the code you passed in but also registers a number of additional error
codes. The `MessageCodesResolver` determines which error codes the `Errors` interface registers.
By default, the `DefaultMessageCodesResolver` is used, which (for example) not only
registers a message with the code you gave but also registers messages that include the field
name you passed to the reject method. So, if you reject a field by using
`rejectValue("age", "too.darn.old")`, apart from the `too.darn.old` code, Spring
also registers `too.darn.old.age` and `too.darn.old.age.int` (the first includes
the field name and the second includes the type of the field). This is done as a
convenience to aid developers when targeting error messages.
We covered databinding and validation. This section covers outputting messages that correspond
to validation errors. In the example shown in the <<validator, preceding section>>,
we rejected the `name` and `age` fields. If we want to output the error messages by using a
`MessageSource`, we can do so using the error code we provide when rejecting the field
('name' and 'age' in this case). When you call (either directly, or indirectly, by using,
for example, the `ValidationUtils` class) `rejectValue` or one of the other `reject` methods
from the `Errors` interface, the underlying implementation not only registers the code you
passed in but also registers a number of additional error codes. The `MessageCodesResolver`
determines which error codes the `Errors` interface registers. By default, the
`DefaultMessageCodesResolver` is used, which (for example) not only registers a message
with the code you gave but also registers messages that include the field name you passed
to the reject method. So, if you reject a field by using `rejectValue("age", "too.darn.old")`,
apart from the `too.darn.old` code, Spring also registers `too.darn.old.age` and
`too.darn.old.age.int` (the first includes the field name and the second includes the type
of the field). This is done as a convenience to aid developers when targeting error messages.
More information on the `MessageCodesResolver` and the default strategy can be found
in the javadoc of
@ -253,8 +253,8 @@ object. The following table shows some examples of these conventions: @@ -253,8 +253,8 @@ object. The following table shows some examples of these conventions:
(This next section is not vitally important to you if you do not plan to work with
the `BeanWrapper` directly. If you use only the `DataBinder` and the `BeanFactory`
and their default implementations, you should skip ahead to the <<beans-beans-conversion,section about
`PropertyEditors`>>.)
and their default implementations, you should skip ahead to the
<<beans-beans-conversion, section on `PropertyEditors`>>.)
The following two example classes use the `BeanWrapper` to get and set
properties:
@ -521,17 +521,17 @@ where it can be automatically detected and applied. @@ -521,17 +521,17 @@ where it can be automatically detected and applied.
Note that all bean factories and application contexts automatically use a number of
built-in property editors, through their use a `BeanWrapper` to
handle property conversions. The standard property editors that the `BeanWrapper`
registers are listed in <<beans-beans-conversion,the previous section>>. Additionally,
`ApplicationContexts` also override or add additional editors to handle
registers are listed in the <<beans-beans-conversion, previous section>>.
Additionally, `ApplicationContexts` also override or add additional editors to handle
resource lookups in a manner appropriate to the specific application context type.
Standard JavaBeans `PropertyEditor` instances are used to convert property values
expressed as strings to the actual complex type of the property.
You can use `CustomEditorConfigurer`, a bean factory post-processor, to conveniently add
expressed as strings to the actual complex type of the property. You can use
`CustomEditorConfigurer`, a bean factory post-processor, to conveniently add
support for additional `PropertyEditor` instances to an `ApplicationContext`.
Consider the following example, which defines a user class called `ExoticType` and another class called `DependsOnExoticType`, which needs
`ExoticType` set as a property:
Consider the following example, which defines a user class called `ExoticType` and
another class called `DependsOnExoticType`, which needs `ExoticType` set as a property:
[source,java,indent=0]
[subs="verbatim,quotes"]
@ -605,14 +605,15 @@ Finally, the following example shows how to use `CustomEditorConfigurer` to regi @@ -605,14 +605,15 @@ Finally, the following example shows how to use `CustomEditorConfigurer` to regi
Another mechanism for registering property editors with the Spring container is to
create and use a `PropertyEditorRegistrar`. This interface is particularly useful when
you need to use the same set of property editors in several different situations. You can write
a corresponding registrar and reuse it in each case. `PropertyEditorRegistrar` instances work
in conjunction with an interface called `PropertyEditorRegistry`, an interface that is
implemented by the Spring `BeanWrapper` (and `DataBinder`). `PropertyEditorRegistrar` instances
are particularly convenient when used in conjunction with `CustomEditorConfigurer`
(described <<beans-beans-conversion-customeditor-registration,here>>), which exposes a
property called `setPropertyEditorRegistrars(..)`. `PropertyEditorRegistrar` instances added to a
`CustomEditorConfigurer` in this fashion can easily be shared with `DataBinder` and
you need to use the same set of property editors in several different situations.
You can write a corresponding registrar and reuse it in each case.
`PropertyEditorRegistrar` instances work in conjunction with an interface called
`PropertyEditorRegistry`, an interface that is implemented by the Spring `BeanWrapper`
(and `DataBinder`). `PropertyEditorRegistrar` instances are particularly convenient
when used in conjunction with `CustomEditorConfigurer` (described
<<beans-beans-conversion-customeditor-registration, here>>), which exposes a property
called `setPropertyEditorRegistrars(..)`. `PropertyEditorRegistrar` instances added
to a `CustomEditorConfigurer` in this fashion can easily be shared with `DataBinder` and
Spring MVC controllers. Furthermore, it avoids the need for synchronization on custom
editors: A `PropertyEditorRegistrar` is expected to create fresh `PropertyEditor`
instances for each bean creation attempt.
@ -659,7 +660,7 @@ The next example shows how to configure a `CustomEditorConfigurer` and inject an @@ -659,7 +660,7 @@ 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 <<web.adoc#mvc,Spring's MVC web framework>>), using `PropertyEditorRegistrars` in
using <<web.adoc#mvc, Spring's MVC web framework>>), using `PropertyEditorRegistrars` in
conjunction with data-binding `Controllers` (such as `SimpleFormController`) can be very
convenient. The following example uses a `PropertyEditorRegistrar` in the
implementation of an `initBinder(..)` method:
@ -954,8 +955,7 @@ It is also common to use a `ConversionService` within a Spring MVC application. @@ -954,8 +955,7 @@ It is also common to use a `ConversionService` within a Spring MVC application.
<<web.adoc#mvc-config-conversion, Conversion and Formatting>> in the Spring MVC chapter.
In certain situations, you may wish to apply formatting during conversion. See
<<format-FormatterRegistry-SPI>> for details on using
`FormattingConversionServiceFactoryBean`.
<<format-FormatterRegistry-SPI>> for details on using `FormattingConversionServiceFactoryBean`.

6
src/docs/asciidoc/data-access-appendix.adoc

@ -18,7 +18,7 @@ This part of the appendix lists XML schemas for data access, including the follo @@ -18,7 +18,7 @@ This part of the appendix lists XML schemas for data access, including the follo
The `tx` tags deal with configuring all of those beans in Spring's comprehensive support
for transactions. These tags are covered in the chapter entitled
<<data-access.adoc#transaction,Transaction Management>>.
<<data-access.adoc#transaction, Transaction Management>>.
TIP: We strongly encourage you to look at the `'spring-tx.xsd'` file that ships with the
Spring distribution. This file contains the XML Schema for Spring's transaction
@ -65,8 +65,8 @@ to you. @@ -65,8 +65,8 @@ to you.
The `jdbc` elements let you quickly configure an embedded database or initialize an
existing data source. These elements are documented in
<<data-access.adoc#jdbc-embedded-database-support,Embedded Database Support>> and
<<data-access.adoc#jdbc-initializing-datasource,Initializing a DataSource>>, respectively.
<<data-access.adoc#jdbc-embedded-database-support, Embedded Database Support>> and
<<data-access.adoc#jdbc-initializing-datasource, Initializing a DataSource>>, respectively.
To use the elements in the `jdbc` schema, you need to have the following preamble at the
top of your Spring XML configuration file. The text in the following snippet references

167
src/docs/asciidoc/data-access.adoc

@ -26,33 +26,34 @@ management that delivers the following benefits: @@ -26,33 +26,34 @@ management that delivers the following benefits:
* A consistent programming model across different transaction APIs, such as Java
Transaction API (JTA), JDBC, Hibernate, and the Java Persistence API (JPA).
* Support for <<transaction-declarative,declarative transaction management>>.
* A simpler API for <<transaction-programmatic,programmatic>> transaction management than
complex transaction APIs, such as JTA.
* Support for <<transaction-declarative, declarative transaction management>>.
* A simpler API for <<transaction-programmatic, programmatic>> transaction management
than complex transaction APIs, such as JTA.
* Excellent integration with Spring's data access abstractions.
The following sections describe the Spring Framework's transaction features and
technologies:
* <<transaction-motivation,Advantages of the Spring Framework's transaction support
* <<transaction-motivation, Advantages of the Spring Framework's transaction support
model>> describes why you would use the Spring Framework's transaction abstraction
instead of EJB Container-Managed Transactions (CMT) or choosing to drive local
transactions through a proprietary API, such as Hibernate.
* <<transaction-strategies,Understanding the Spring Framework transaction abstraction>>
* <<transaction-strategies, Understanding the Spring Framework transaction abstraction>>
outlines the core classes and describes how to configure and obtain `DataSource`
instances from a variety of sources.
* <<tx-resource-synchronization,Synchronizing resources with transactions>> describes
* <<tx-resource-synchronization, Synchronizing resources with transactions>> describes
how the application code ensures that resources are created, reused, and cleaned up
properly.
* <<transaction-declarative,Declarative transaction management>> describes support for
* <<transaction-declarative, Declarative transaction management>> describes support for
declarative transaction management.
* <<transaction-programmatic,Programmatic transaction management>> covers support for
* <<transaction-programmatic, Programmatic transaction management>> covers support for
programmatic (that is, explicitly coded) transaction management.
* <<transaction-event,Transaction bound event>> describes how you could use application
* <<transaction-event, Transaction bound event>> describes how you could use application
events within a transaction.
(The chapter also includes discussions of best practices, <<transaction-application-server-integration,application
server integration>>, and <<transaction-solutions-to-common-problems,solutions to common problems>>.)
The chapter also includes discussions of best practices,
<<transaction-application-server-integration, application server integration>>,
and <<transaction-solutions-to-common-problems, solutions to common problems>>.
@ -167,7 +168,7 @@ strategy. A transaction strategy is defined by the @@ -167,7 +168,7 @@ strategy. A transaction strategy is defined by the
----
This is primarily a service provider interface (SPI), although you can use it
<<transaction-programmatic-ptm,programmatically>> from your application code. Because
<<transaction-programmatic-ptm, programmatically>> from your application code. Because
`PlatformTransactionManager` is an interface, it can be easily mocked or stubbed as
necessary. It is not tied to a lookup strategy, such as JNDI.
`PlatformTransactionManager` implementations are defined like any other object (or bean)
@ -301,8 +302,8 @@ The `JtaTransactionManager` does not need to know about the `DataSource` (or any @@ -301,8 +302,8 @@ The `JtaTransactionManager` does not need to know about the `DataSource` (or any
specific resources) because it uses the container's global transaction management
infrastructure.
NOTE: The preceding definition of the `dataSource` bean uses the `<jndi-lookup/>` tag from the
`jee` namespace. For more information see
NOTE: The preceding definition of the `dataSource` bean uses the `<jndi-lookup/>` tag
from the `jee` namespace. For more information see
<<integration.adoc#xsd-schemas-jee, The JEE Schema>>.
You can also use easily Hibernate local transactions, as shown in the following
@ -312,9 +313,9 @@ which your application code can use to obtain Hibernate `Session` instances. @@ -312,9 +313,9 @@ which your application code can use to obtain Hibernate `Session` instances.
The `DataSource` bean definition is similar to the local JDBC example shown
previously and, thus, is not shown in the following example.
NOTE: If the `DataSource` (used by any non-JTA transaction manager) is looked up through JNDI and
managed by a Java EE container, it should be non-transactional, because the Spring
Framework (rather than the Java EE container) manages the transactions.
NOTE: If the `DataSource` (used by any non-JTA transaction manager) is looked up through
JNDI and managed by a Java EE container, it should be non-transactional, because the
Spring Framework (rather than the Java EE container) manages the transactions.
The `txManager` bean in this case is of the `HibernateTransactionManager` type. In the
same way as the `DataSourceTransactionManager` needs a reference to the `DataSource`,
@ -472,7 +473,7 @@ necessary. The differences between the two types of transaction management are: @@ -472,7 +473,7 @@ necessary. The differences between the two types of transaction management are:
* You can apply the Spring Framework declarative transaction management to any class,
not merely special classes such as EJBs.
* The Spring Framework offers declarative
<<transaction-declarative-rolling-back,rollback rules>>, a feature with no EJB
<<transaction-declarative-rolling-back, rollback rules>>, a feature with no EJB
equivalent. Both programmatic and declarative support for rollback rules is provided.
* The Spring Framework lets you customize transactional behavior by using AOP.
For example, you can insert custom behavior in the case of transaction rollback. You
@ -484,16 +485,6 @@ necessary. The differences between the two types of transaction management are: @@ -484,16 +485,6 @@ necessary. The differences between the two types of transaction management are:
recommend that you use EJB. However, consider carefully before using such a feature,
because, normally, one does not want transactions to span remote calls.
.Where is TransactionProxyFactoryBean?
****
Declarative transaction configuration in versions of Spring 2.0 and above differs
considerably from previous versions of Spring. The main difference is that there is no
longer any need to configure `TransactionProxyFactoryBean` beans.
The pre-Spring 2.0 configuration style is still 100% valid configuration. Think of the
new `<tx:tags/>` as defining `TransactionProxyFactoryBean` beans on your behalf.
****
The concept of rollback rules is important. They let you specify which exceptions
(and throwables) should cause automatic rollback. You can specify this declaratively, in
configuration, not in Java code. So, although you can still call `setRollbackOnly()` on
@ -522,7 +513,7 @@ transaction infrastructure in the event of transaction-related issues. @@ -522,7 +513,7 @@ transaction infrastructure in the event of transaction-related issues.
The most important concepts to grasp with regard to the Spring Framework's declarative
transaction support are that this support is enabled
<<core.adoc#aop-understanding-aop-proxies,via AOP proxies>> and that the transactional
<<core.adoc#aop-understanding-aop-proxies, via AOP proxies>> and that the transactional
advice is driven by metadata (currently XML- or annotation-based). The combination of
AOP with transactional metadata yields an AOP proxy that uses a `TransactionInterceptor`
in conjunction with an appropriate `PlatformTransactionManager` implementation to drive
@ -673,13 +664,14 @@ attribute explicitly, as in the preceding example. @@ -673,13 +664,14 @@ attribute explicitly, as in the preceding example.
The `<aop:config/>` definition ensures that the transactional advice defined by the
`txAdvice` bean executes at the appropriate points in the program. First, you define a
pointcut that matches the execution of any operation defined in the `FooService`
interface ( `fooServiceOperation`). Then you associate the pointcut with the `txAdvice`
by using an advisor. The result indicates that, at the execution of a `fooServiceOperation`,
pointcut that matches the execution of any operation defined in the `FooService` interface
(`fooServiceOperation`). Then you associate the pointcut with the `txAdvice` by using an
advisor. The result indicates that, at the execution of a `fooServiceOperation`,
the advice defined by `txAdvice` is run.
The expression defined within the `<aop:pointcut/>` element is an AspectJ pointcut
expression. See <<core.adoc#aop, the AOP section>> for more details on pointcut expressions in Spring.
expression. See <<core.adoc#aop, the AOP section>> for more details on pointcut
expressions in Spring.
A common requirement is to make an entire service layer transactional. The best way to
do this is to change the pointcut expression to match any operation in your
@ -694,18 +686,18 @@ service layer. The following example shows how to do so: @@ -694,18 +686,18 @@ service layer. The following example shows how to do so:
</aop:config>
----
NOTE: In the preceding example, it is assumed that all your service interfaces are defined in the
`x.y.service` package. See <<core.adoc#aop, the AOP section>> for more details.
NOTE: In the preceding example, it is assumed that all your service interfaces are defined
in the `x.y.service` package. See <<core.adoc#aop, the AOP section>> for more details.
Now that we have analyzed the configuration, you may be asking yourself,
"`What does all this configuration actually do?`"
The configuration shown earlier is used to create a transactional proxy around the object
that is created from the `fooService` bean definition. The proxy is configured with
the transactional advice so that, when an appropriate method is invoked on the
proxy, a transaction is started, suspended, marked as read-only, and so on, depending
on the transaction configuration associated with that method. Consider the following
program that test drives the configuration shown earlier:
the transactional advice so that, when an appropriate method is invoked on the proxy,
a transaction is started, suspended, marked as read-only, and so on, depending 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"]
@ -969,7 +961,7 @@ transactional settings: @@ -969,7 +961,7 @@ transactional settings:
This section summarizes the various transactional settings that you can specify by using
the `<tx:advice/>` tag. The default `<tx:advice/>` settings are:
* The <<tx-propagation,propagation setting>> is `REQUIRED.`
* The <<tx-propagation, propagation setting>> is `REQUIRED.`
* The isolation level is `DEFAULT.`
* The transaction is read-write.
* The transaction timeout defaults to the default timeout of the underlying transaction
@ -1184,7 +1176,7 @@ modified) to turn `@Transactional` into runtime behavior on any kind of method. @@ -1184,7 +1176,7 @@ modified) to turn `@Transactional` into runtime behavior on any kind of method.
for classes annotated with the `@Transactional` annotation. If the
`proxy-target-class` attribute is set to `true`, class-based proxies are created.
If `proxy-target-class` is `false` or if the attribute is omitted, then standard JDK
interface-based proxies are created. (See <<core.adoc#aop-proxying, Proxying mechanisms>>
interface-based proxies are created. (See <<core.adoc#aop-proxying, Proxying Mechanisms>>
for a detailed examination of the different proxy types.)
| `order`
@ -1192,7 +1184,7 @@ modified) to turn `@Transactional` into runtime behavior on any kind of method. @@ -1192,7 +1184,7 @@ modified) to turn `@Transactional` into runtime behavior on any kind of method.
| `Ordered.LOWEST_PRECEDENCE`
| Defines the order of the transaction advice that is applied to beans annotated with
`@Transactional`. (For more information about the rules related to ordering of AOP
advice, see <<core.adoc#aop-ataspectj-advice-ordering,Advice Ordering>>.)
advice, see <<core.adoc#aop-ataspectj-advice-ordering, Advice Ordering>>.)
No specified ordering means that the AOP subsystem determines the order of the advice.
|===
@ -1357,7 +1349,7 @@ specifically qualified `PlatformTransactionManager` bean is found. @@ -1357,7 +1349,7 @@ specifically qualified `PlatformTransactionManager` bean is found.
===== Custom Shortcut Annotations
If you find you repeatedly use the same attributes with `@Transactional` on many different
methods, <<core.adoc#beans-meta-annotations,Spring's meta-annotation support>> lets you
methods, <<core.adoc#beans-meta-annotations, Spring's meta-annotation support>> lets you
define custom shortcut annotations for your specific use cases. For example, consider the
following annotation definitions:
@ -2488,7 +2480,7 @@ The following example invokes a stored procedure: @@ -2488,7 +2480,7 @@ The following example invokes a stored procedure:
Long.valueOf(unionId));
----
More sophisticated stored procedure support is <<jdbc-StoredProcedure,covered later>>.
More sophisticated stored procedure support is <<jdbc-StoredProcedure, covered later>>.
[[jdbc-JdbcTemplate-idioms]]
===== `JdbcTemplate` Best Practices
@ -2500,7 +2492,7 @@ The `JdbcTemplate` is stateful, in that it maintains a reference to a `DataSourc @@ -2500,7 +2492,7 @@ The `JdbcTemplate` is stateful, in that it maintains a reference to a `DataSourc
this state is not conversational state.
A common practice when using the `JdbcTemplate` class (and the associated
<<jdbc-NamedParameterJdbcTemplate,`NamedParameterJdbcTemplate`>> class) is to
<<jdbc-NamedParameterJdbcTemplate, `NamedParameterJdbcTemplate`>> class) is to
configure a `DataSource` in your Spring configuration file and then dependency-inject
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:
@ -3748,7 +3740,7 @@ returned `out` parameters. @@ -3748,7 +3740,7 @@ returned `out` parameters.
Earlier in this chapter, we described how parameters are deduced from metadata, but you can declare them
explicitly if you wish. You can do so by creating and configuring `SimpleJdbcCall` with
the `declareParameters` method, which takes a variable number of `SqlParameter` objects
as input. See the <<jdbc-params,next section>> for details on how to define an `SqlParameter`.
as input. See the <<jdbc-params, next section>> for details on how to define an `SqlParameter`.
NOTE: Explicit declarations are necessary if the database you use is not a Spring-supported
database. Currently, Spring supports metadata lookup of stored procedure calls for the
@ -4691,12 +4683,12 @@ call the `setType(EmbeddedDatabaseType)` method with `EmbeddedDatabaseType.DERBY @@ -4691,12 +4683,12 @@ call the `setType(EmbeddedDatabaseType)` method with `EmbeddedDatabaseType.DERBY
Embedded databases provide a lightweight way to test data access code. The next example is a
data access integration test template that uses an embedded database. Using such a template
can be useful for one-offs when the embedded database does not need to be
reused across test classes. However, if you wish to create an embedded database that is
shared within a test suite, consider using the <<testing.adoc#testcontext-framework,Spring TestContext
Framework>> and configuring the embedded database as a bean in the Spring
`ApplicationContext` as described in <<jdbc-embedded-database-xml>> and
<<jdbc-embedded-database-java>>. The following listing shows the test template:
can be useful for one-offs when the embedded database does not need to be reused across test
classes. However, if you wish to create an embedded database that is shared within a test suite,
consider using the <<testing.adoc#testcontext-framework, Spring TestContext Framework>> and
configuring the embedded database as a bean in the Spring `ApplicationContext` as described
in <<jdbc-embedded-database-xml>> and <<jdbc-embedded-database-java>>. The following listing
shows the test template:
[source,java,indent=0]
[subs="verbatim,quotes"]
@ -4983,14 +4975,13 @@ The benefits of using the Spring Framework to create your ORM DAOs include: @@ -4983,14 +4975,13 @@ The benefits of using the Spring Framework to create your ORM DAOs include:
aspect-oriented programming (AOP) style method interceptor either through the
`@Transactional` annotation or by explicitly configuring the transaction AOP advice in
an XML configuration file. In both cases, transaction semantics and exception handling
(rollback and so on) are handled for you. As discussed in
<<orm-resource-mngmnt>>, you can also swap various
transaction managers, without affecting your ORM-related code. For example, you can
swap between local transactions and JTA, with the same full services (such as
declarative transactions) available in both scenarios. Additionally, JDBC-related code
can fully integrate transactionally with the code you use to do ORM. This is useful
for data access that is not suitable for ORM (such as batch processing and BLOB
streaming) but that still needs to share common transactions with ORM operations.
(rollback and so on) are handled for you. As discussed in <<orm-resource-mngmnt>>,
you can also swap various transaction managers, without affecting your ORM-related code.
For example, you can swap between local transactions and JTA, with the same full services
(such as declarative transactions) available in both scenarios. Additionally,
JDBC-related code can fully integrate transactionally with the code you use to do ORM.
This is useful for data access that is not suitable for ORM (such as batch processing and
BLOB streaming) but that still needs to share common transactions with ORM operations.
TIP: For more comprehensive ORM support, including support for alternative database
technologies such as MongoDB, you might want to check out the
@ -5003,8 +4994,8 @@ Data with JPA] guide from https://spring.io provides a great introduction. @@ -5003,8 +4994,8 @@ Data with JPA] guide from https://spring.io provides a great introduction.
[[orm-general]]
=== General ORM Integration Considerations
This section highlights considerations that apply to all ORM technologies. The
<<orm-hibernate>> section provides more details and also show these features and
This section highlights considerations that apply to all ORM technologies.
The <<orm-hibernate>> section provides more details and also show these features and
configurations in a concrete context.
The major goal of Spring's ORM integration is clear application layering (with any data
@ -5033,10 +5024,11 @@ interceptors for the ORM technologies. @@ -5033,10 +5024,11 @@ interceptors for the ORM technologies.
The infrastructure provides proper resource handling and appropriate conversion of
specific API exceptions to an unchecked infrastructure exception hierarchy. Spring
introduces a DAO exception hierarchy, applicable to any data access strategy. For direct
JDBC, the `JdbcTemplate` class mentioned in a <<jdbc-JdbcTemplate,previous section>> provides connection
handling and proper conversion of `SQLException` to the `DataAccessException` hierarchy,
including translation of database-specific SQL error codes to meaningful exception
classes. For ORM technologies, see the <<orm-exception-translation,next section>> for how to get the same exception
JDBC, the `JdbcTemplate` class mentioned in a <<jdbc-JdbcTemplate, previous section>>
provides connection handling and proper conversion of `SQLException` to the
`DataAccessException` hierarchy, including translation of database-specific SQL error
codes to meaningful exception classes. For ORM technologies, see the
<<orm-exception-translation, next section>> for how to get the same exception
translation benefits.
When it comes to transaction management, the `JdbcTemplate` class hooks in to the Spring
@ -5121,7 +5113,7 @@ To avoid tying application objects to hard-coded resource lookups, you can defin @@ -5121,7 +5113,7 @@ To avoid tying application objects to hard-coded resource lookups, you can defin
resources (such as a JDBC `DataSource` or a Hibernate `SessionFactory`) as beans in the
Spring container. Application objects that need to access resources receive references
to such predefined instances through bean references, as illustrated in the DAO
definition in the <<orm-hibernate-straight,next section>>.
definition in the <<orm-hibernate-straight, next section>>.
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:
@ -5185,7 +5177,7 @@ property. On the programmatic `LocalSessionFactoryBuilder`, there is an overload @@ -5185,7 +5177,7 @@ property. On the programmatic `LocalSessionFactoryBuilder`, there is an overload
As of Spring Framework 5.1, such a native Hibernate setup can also expose a JPA
`EntityManagerFactory` for standard JPA interaction next to native Hibernate access.
See <<orm-jpa-hibernate,Native Hibernate Setup for JPA>> for details.
See <<orm-jpa-hibernate, Native Hibernate Setup for JPA>> for details.
====
@ -5657,7 +5649,7 @@ NOTE: If you want to specifically configure a Hibernate setup, an immediate alte @@ -5657,7 +5649,7 @@ NOTE: If you want to specifically configure a Hibernate setup, an immediate alte
to go with Hibernate 5.2 or 5.3 and set up a native Hibernate `LocalSessionFactoryBean`
instead of a plain JPA `LocalContainerEntityManagerFactoryBean`, letting it interact
with JPA access code as well as native Hibernate access code.
See <<orm-jpa-hibernate,Native Hibernate setup for JPA interaction>> for details.
See <<orm-jpa-hibernate, Native Hibernate setup for JPA interaction>> for details.
The `LocalContainerEntityManagerFactoryBean` gives full control over
`EntityManagerFactory` configuration and is appropriate for environments where
@ -5739,18 +5731,17 @@ Spring provides a number of `LoadTimeWeaver` implementations for various environ @@ -5739,18 +5731,17 @@ Spring provides a number of `LoadTimeWeaver` implementations for various environ
letting `ClassTransformer` instances be applied only for each class loader and not
for each VM.
See <<core.adoc#aop-aj-ltw-spring,Spring configuration>> in the AOP chapter for
See the <<core.adoc#aop-aj-ltw-spring, Spring configuration>> in the AOP chapter for
more insight regarding the `LoadTimeWeaver` implementations and their setup, either
generic or customized to various platforms (such as Tomcat, WebLogic, GlassFish,
Resin, and JBoss).
generic or customized to various platforms (such as Tomcat, JBoss and WebSphere).
As described in <<core.adoc#aop-aj-ltw-spring,Spring configuration>>, you can configure a context-wide
`LoadTimeWeaver` by using the `@EnableLoadTimeWeaving` annotation of the
`context:load-time-weaver` XML element. Such a global weaver is automatically picked up by all JPA
`LocalContainerEntityManagerFactoryBean` instances. The following example shows the preferred way of
setting up a load-time weaver, delivering auto-detection of the platform (WebLogic,
GlassFish, Tomcat, Resin, JBoss, or VM agent) and automatic propagation of the weaver to
all weaver-aware beans:
As described in <<core.adoc#aop-aj-ltw-spring, Spring configuration>>, you can configure
a context-wide `LoadTimeWeaver` by using the `@EnableLoadTimeWeaving` annotation of the
`context:load-time-weaver` XML element. Such a global weaver is automatically picked u
by all JPA `LocalContainerEntityManagerFactoryBean` instances. The following example
shows the preferred way of setting up a load-time weaver, delivering auto-detection
of the platform (e.g. Tomcat's weaving-capable class loader or Spring's JVM agent)
and automatic propagation of the weaver to all weaver-aware beans:
[source,xml,indent=0]
[subs="verbatim,quotes"]
@ -5976,8 +5967,8 @@ Even though the new DAO implementation uses method-level @@ -5976,8 +5967,8 @@ Even though the new DAO implementation uses method-level
injection of an `EntityManager` instead of an `EntityManagerFactory`, no change is
required in the application context XML, due to annotation usage.
The main advantage of this DAO style is that it depends only on the Java Persistence API. No
import of any Spring class is required. Moreover, as the JPA annotations are understood,
The main advantage of this DAO style is that it depends only on the Java Persistence API.
No import of any Spring class is required. Moreover, as the JPA annotations are understood,
the injections are applied automatically by the Spring container. This is appealing from
a non-invasiveness perspective and can feel more natural to JPA developers.
@ -5985,8 +5976,8 @@ a non-invasiveness perspective and can feel more natural to JPA developers. @@ -5985,8 +5976,8 @@ a non-invasiveness perspective and can feel more natural to JPA developers.
[[orm-jpa-tx]]
==== Spring-driven JPA transactions
NOTE: We strongly encourage you to read <<transaction-declarative>>, if you have not already done
so, to get more detailed coverage of Spring's declarative transaction support.
NOTE: We strongly encourage you to read <<transaction-declarative>>, if you have not
already done so, to get more detailed coverage of Spring's declarative transaction support.
The recommended strategy for JPA is local transactions through JPA's native transaction
support. Spring's `JpaTransactionManager` provides many capabilities known from local
@ -5997,13 +5988,13 @@ Spring JPA also lets a configured `JpaTransactionManager` expose a JPA transacti @@ -5997,13 +5988,13 @@ Spring JPA also lets a configured `JpaTransactionManager` expose a JPA transacti
to JDBC access code that accesses the same `DataSource`, provided that the registered
`JpaDialect` supports retrieval of the underlying JDBC `Connection`.
Spring provides dialects for the EclipseLink and Hibernate JPA implementations.
See the <<orm-jpa-dialect,next section>> for details on the `JpaDialect` mechanism.
See the <<orm-jpa-dialect, next section>> for details on the `JpaDialect` mechanism.
NOTE: As an immediate alternative, Spring's native `HibernateTransactionManager` is capable
of interacting with JPA access code as of Spring Framework 5.1 and Hibernate 5.2/5.3,
adapting to several Hibernate specifics and providing JDBC interaction.
This makes particular sense in combination with `LocalSessionFactoryBean` setup.
See <<orm-jpa-hibernate,Native Hibernate Setup for JPA Interaction>> for details.
See <<orm-jpa-hibernate, Native Hibernate Setup for JPA Interaction>> for details.
[[orm-jpa-dialect]]
@ -6100,7 +6091,7 @@ seamlessly integrating with `@Bean` style configuration (no `FactoryBean` involv @@ -6100,7 +6091,7 @@ seamlessly integrating with `@Bean` style configuration (no `FactoryBean` involv
====
`LocalSessionFactoryBean` and `LocalSessionFactoryBuilder` support background
bootstrapping, just as the JPA `LocalContainerEntityManagerFactoryBean` does.
See <<orm-jpa-setup-background,Background Bootstrapping>> for an introduction.
See <<orm-jpa-setup-background, Background Bootstrapping>> for an introduction.
On `LocalSessionFactoryBean`, this is available through the `bootstrapExecutor`
property. On the programmatic `LocalSessionFactoryBuilder`, an overloaded
@ -6169,8 +6160,8 @@ These runtime exceptions wrap the original exception so that no information is l @@ -6169,8 +6160,8 @@ These runtime exceptions wrap the original exception so that no information is l
[[oxm-marshaller-unmarshaller]]
=== `Marshaller` and `Unmarshaller`
As stated in the <<oxm-introduction,introduction>>, a marshaller serializes an object to XML, and an
unmarshaller deserializes XML stream to an object. This section describes
As stated in the <<oxm-introduction, introduction>>, a marshaller serializes an object
to XML, and an unmarshaller deserializes XML stream to an object. This section describes
the two Spring interfaces used for this purpose.

20
src/docs/asciidoc/index.adoc

@ -3,23 +3,23 @@ @@ -3,23 +3,23 @@
:api-spring-framework: {doc-root}/spring-framework/docs/{spring-version}/javadoc-api/org/springframework
****
_What's New_, _Upgrade Notes_, _Supported Versions_, and other topics, independent of
release cadence, are maintained externaly on the project's
_What's New_, _Upgrade Notes_, _Supported Versions_, and other topics,
independent of release cadence, are maintained externaly on the project's
https://github.com/spring-projects/spring-framework/wiki[*Github Wiki*].
****
[horizontal]
<<overview.adoc#overview,Overview>> :: history, design philosophy,feedback,
<<overview.adoc#overview, Overview>> :: history, design philosophy,feedback,
getting started.
<<core.adoc#spring-core,Core>> :: IoC container, Events, Resources, i18n, Validation,
<<core.adoc#spring-core, Core>> :: IoC container, Events, Resources, i18n, Validation,
Data Binding, Type Conversion, SpEL, AOP.
<<testing.adoc#testing,Testing>> :: Mock objects, TestContext framework,
<<testing.adoc#testing, Testing>> :: Mock objects, TestContext framework,
Spring MVC Test, WebTestClient.
<<data-access.adoc#spring-data-tier,Data Access>> :: Transactions, DAO support, JDBC,
<<data-access.adoc#spring-data-tier, Data Access>> :: Transactions, DAO support, JDBC,
ORM, Marshalling XML.
<<web.adoc#spring-web,Web Servlet>> :: Spring MVC, WebSocket, SockJS, STOMP messaging.
<<web-reactive.adoc#spring-webflux,Web Reactive>> :: Spring WebFlux,
<<web.adoc#spring-web, Web Servlet>> :: Spring MVC, WebSocket, SockJS, STOMP messaging.
<<web-reactive.adoc#spring-webflux, Web Reactive>> :: Spring WebFlux,
WebClient, WebSocket.
<<integration.adoc#spring-integration,Integration>> :: Remoting, JMS, JCA, JMX, Email,
<<integration.adoc#spring-integration, Integration>> :: Remoting, JMS, JCA, JMX, Email,
Tasks, Scheduling, Cache.
<<languages.adoc#languages,Languages>> :: Kotlin, Groovy, Dynamic languages.
<<languages.adoc#languages, Languages>> :: Kotlin, Groovy, Dynamic languages.

8
src/docs/asciidoc/integration-appendix.adoc

@ -283,8 +283,8 @@ SessionBean with `jee`: @@ -283,8 +283,8 @@ SessionBean with `jee`:
=== The `jms` Schema
The `jms` elements deal with configuring JMS-related beans, such as Spring's
<<integration.adoc#jms-mdp,Message Listener Containers>>. These elements are detailed in the
section of the <<integration.adoc#jms,JMS chapter>> entitled <<integration.adoc#jms-namespace,
<<integration.adoc#jms-mdp, Message Listener Containers>>. These elements are detailed in the
section of the <<integration.adoc#jms, JMS chapter>> entitled <<integration.adoc#jms-namespace,
JMS Namespace Support>>. See that chapter for full details on this support
and the `jms` elements themselves.
@ -322,8 +322,8 @@ This element is detailed in @@ -322,8 +322,8 @@ This element is detailed in
You can use the `cache` elements to enable support for Spring's `@CacheEvict`, `@CachePut`,
and `@Caching` annotations. It it also supports declarative XML-based caching. See
<<integration.adoc#cache-annotation-enable,Enabling Caching Annotations>> and
<<integration.adoc#cache-declarative-xml,Declarative XML-based Caching>> for details.
<<integration.adoc#cache-annotation-enable, Enabling Caching Annotations>> and
<<integration.adoc#cache-declarative-xml, Declarative XML-based Caching>> for details.
To use the elements in the `cache` schema, you need to have the following preamble at the
top of your Spring XML configuration file. The text in the following snippet references

797
src/docs/asciidoc/integration.adoc

File diff suppressed because it is too large Load Diff

276
src/docs/asciidoc/languages/dynamic-languages.adoc

@ -1,29 +1,20 @@ @@ -1,29 +1,20 @@
[[dynamic-language]]
= Dynamic Language Support
Spring 2.0 introduced comprehensive support for using classes and objects that have been
defined by using a dynamic language (such as JRuby) with Spring. This support lets you
write any number of classes in a supported dynamic language and have the Spring
Spring provides comprehensive support for using classes and objects that have been
defined by using a dynamic language (such as Groovy) with Spring. This support lets
you write any number of classes in a supported dynamic language and have the Spring
container transparently instantiate, configure, and dependency inject the resulting
objects.
Spring currently supports the following dynamic languages:
Spring's scripting support primarily targets Groovy and BeanShell. Beyond those
specifically supported languages, the JSR-223 scripting mechanism is supported
for integration with any JSR-223 capable language provider (as of Spring 4.2),
e.g. JRuby.
* JRuby 1.5+
* Groovy 1.8+
* BeanShell 2.0
You can find fully working examples of where this dynamic language support can be
immediately useful in <<dynamic-language-scenarios>>.
.Why only these languages?
****
We chose to support these languages because:
* The languages have a lot of traction in the Java enterprise community.
* No requests were made for other languages at the time that this support was added
* The Spring developers were most familiar with them.
****
You can find fully working examples of where this dynamic language support can be immediately useful
in <<dynamic-language-scenarios>>.
@ -37,9 +28,9 @@ language for this first bean is Groovy. (The basis of this example was taken fro @@ -37,9 +28,9 @@ language for this first bean is Groovy. (The basis of this example was taken fro
Spring test suite. If you want to see equivalent examples in any of the other
supported languages, take a look at the source code).
The next example shows the `Messenger` interface, which the Groovy bean is going to implement.
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
The next example shows the `Messenger` interface, which the Groovy bean is going to
implement. 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]
@ -50,7 +41,6 @@ implementation is a Groovy script. The following listing shows the `Messenger` i @@ -50,7 +41,6 @@ implementation is a Groovy script. The following listing shows the `Messenger` i
public interface Messenger {
String getMessage();
}
----
@ -72,7 +62,6 @@ The following example defines a class that has a dependency on the `Messenger` i @@ -72,7 +62,6 @@ The following example defines a class that has a dependency on the `Messenger` i
public void processBooking() {
// use the injected Messenger object...
}
}
----
@ -91,7 +80,6 @@ The following example implements the `Messenger` interface in Groovy: @@ -91,7 +80,6 @@ The following example implements the `Messenger` interface in Groovy:
class GroovyMessenger implements Messenger {
String message
}
----
@ -105,7 +93,7 @@ implementation is supported, but you have to manage the plumbing of the Spring i @@ -105,7 +93,7 @@ implementation is supported, but you have to manage the plumbing of the Spring i
to do so.
For more information on schema-based configuration, see <<appendix.adoc#xsd-configuration,
XML Schema-based configuration>>.
XML Schema-based Configuration>>.
====
Finally, the following example shows the bean definitions that effect the injection of the
@ -135,14 +123,14 @@ Groovy-defined `Messenger` implementation into an instance of the @@ -135,14 +123,14 @@ Groovy-defined `Messenger` implementation into an instance of the
</beans>
----
The `bookingService` bean (a `DefaultBookingService`) can now use its private
`messenger` member variable as normal, because the `Messenger` instance that was injected
into it is a `Messenger` instance. There is nothing special going on here -- just
plain Java and plain Groovy.
The `bookingService` bean (a `DefaultBookingService`) can now use its private `messenger`
member variable as normal, because the `Messenger` instance that was injected into it is
a `Messenger` instance. There is nothing special going on here -- just plain Java and
plain Groovy.
Hopefully, the preceding XML snippet is self-explanatory, but do not worry unduly if it is not.
Keep reading for the in-depth detail on the whys and wherefores of the preceding
configuration.
Keep reading for the in-depth detail on the whys and wherefores of the preceding configuration.
@ -152,11 +140,11 @@ configuration. @@ -152,11 +140,11 @@ configuration.
This section describes exactly how you define Spring-managed beans in any of the
supported dynamic languages.
Note that this chapter does not attempt to explain the syntax and idioms of the
supported dynamic languages. For example, if you want to use Groovy to write certain of
the classes in your application, we assume that you already know Groovy. If
you need further details about the dynamic languages themselves, see
<<dynamic-language-resources>> at the end of this chapter.
Note that this chapter does not attempt to explain the syntax and idioms of the supported
dynamic languages. For example, if you want to use Groovy to write certain of the classes
in your application, we assume that you already know Groovy. If you need further details
about the dynamic languages themselves, see <<dynamic-language-resources>> at the end of
this chapter.
@ -183,45 +171,43 @@ Spring's dynamic language support does make some (small) assumptions about the c @@ -183,45 +171,43 @@ Spring's dynamic language support does make some (small) assumptions about the c
of your dynamic language source files.
[[dynamic-language-beans-concepts-xml-language-element]]
==== The <lang:language/> element
The final step in the list in the <<dynamic-language-beans-concepts,preceding section>> involves defining dynamic-language-backed bean definitions, one for each
bean that you want to configure (this is no different from normal JavaBean
configuration). However, instead of specifying the fully qualified classname of the
class that is to be instantiated and configured by the container, you can use the
`<lang:language/>` element to define the dynamic language-backed bean.
The final step in the list in the <<dynamic-language-beans-concepts, preceding section>>
involves defining dynamic-language-backed bean definitions, one for each bean that you
want to configure (this is no different from normal JavaBean configuration). However,
instead of specifying the fully qualified classname of the class that is to be
instantiated and configured by the container, you can use the `<lang:language/>`
element to define the dynamic language-backed bean.
Each of the supported languages has a corresponding `<lang:language/>` element:
* `<lang:groovy/>` (Groovy)
* `<lang:bsh/>` (BeanShell)
* `<lang:std/>` (JSR-223)
* `<lang:std/>` (JSR-223, e.g. with JRuby)
The exact attributes and child elements that are available for configuration depends on
exactly which language the bean has been defined in (the language-specific sections
later in this chapter detail this).
[[dynamic-language-refreshable-beans]]
==== Refreshable Beans
One of the (and perhaps the single) most compelling value adds of the dynamic language support
in Spring is the "`refreshable bean`" feature.
One of the (and perhaps the single) most compelling value adds of the dynamic language
support in Spring is the "`refreshable bean`" feature.
A refreshable bean is a dynamic-language-backed bean. With a small amount of
configuration, a dynamic-language-backed bean can monitor changes in its underlying
source file resource and then reload itself when the dynamic language source file is
changed (for example, when you edit and save changes to the file on the
file system).
changed (for example, when you edit and save changes to the file on the file system).
This lets you deploy any number of dynamic language source files as part of
an application, configure the Spring container to create beans backed by dynamic
This lets you deploy any number of dynamic language source files as part of an
application, configure the Spring container to create beans backed by dynamic
language source files (using the mechanisms described in this chapter), and (later,
as requirements change or some other external factor comes into play) edit a
dynamic language source file and have any change they make be reflected in the bean that is
as requirements change or some other external factor comes into play) edit a dynamic
language source file and have any change they make be reflected in the bean that is
backed by the changed dynamic language source file. There is no need to shut down a
running application (or redeploy in the case of a web application). The
dynamic-language-backed bean so amended picks up the new state and logic from the
@ -230,11 +216,11 @@ changed dynamic language source file. @@ -230,11 +216,11 @@ changed dynamic language source file.
NOTE: This feature is off by default.
Now we can take a look at an example to see how easy it is to start using refreshable
beans. To turn on the refreshable beans feature, you have to specify exactly
one additional attribute on the `<lang:language/>` element of your bean definition.
So, if we stick with <<dynamic-language-a-first-example,the example>> from earlier in this
chapter, the following example shows what we would change in the Spring XML configuration to effect
refreshable beans:
beans. To turn on the refreshable beans feature, you have to specify exactly one
additional attribute on the `<lang:language/>` element of your bean definition. So,
if we stick with <<dynamic-language-a-first-example, the example>> from earlier in
this 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"]
@ -257,17 +243,17 @@ refreshable beans: @@ -257,17 +243,17 @@ 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
refreshed with any changes made to the underlying dynamic language source file. You can
turn off the refresh behavior by assigning a negative value to the
refreshed with any changes made to the underlying dynamic language source file.
You can turn off the refresh behavior by assigning a negative value to the
`refresh-check-delay` attribute. Remember that, by default, the refresh behavior is
disabled. If you do not want the refresh behavior, do not define the attribute.
If we then run the following application, we can exercise the refreshable feature (Please
do excuse the "`jumping-through-hoops-to-pause-the-execution`" shenanigans in this
next slice of code.) The `System.in.read()` call is only there so that the execution of
the program pauses while you (the developer in this scenario) go off and edit the underlying dynamic language
source file so that the refresh triggers on the dynamic-language-backed bean when
the program resumes execution.
If we then run the following application, we can exercise the refreshable feature.
(Please excuse the "`jumping-through-hoops-to-pause-the-execution`" shenanigans
in this next slice of code.) The `System.in.read()` call is only there so that the
execution of the program pauses while you (the developer in this scenario) go off
and edit the underlying dynamic language source file so that the refresh triggers
on the dynamic-language-backed bean when the program resumes execution.
The following listing shows this sample application:
@ -291,10 +277,11 @@ The following listing shows this sample application: @@ -291,10 +277,11 @@ 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:
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"]
@ -316,15 +303,14 @@ message is surrounded by quotation marks. The following listing shows the change @@ -316,15 +303,14 @@ 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
execution, the result of calling the `getMessage()` method on the
dynamic-language-backed `Messenger` implementation is `'I Can Do The Frug'`
(notice the inclusion of the additional quotation marks).
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 execution,
the result of calling the `getMessage()` method on the dynamic-language-backed
`Messenger` implementation is `'I Can Do The Frug'` (notice the inclusion of the
additional quotation marks).
Changes to a script do not trigger a refresh if
the changes occur within the window of the `refresh-check-delay` value.
Changes to the script are not actually picked up until
Changes to a script do not trigger a refresh if the changes occur within the window of
the `refresh-check-delay` value. Changes to the script are not actually picked up until
a method is called on the dynamic-language-backed bean. It is only when a method is
called on a dynamic-language-backed bean that it checks to see if its underlying script
source has changed. Any exceptions that relate to refreshing the script (such as
@ -339,7 +325,6 @@ that checks the last modified date of a dynamic language source file that exists @@ -339,7 +325,6 @@ that checks the last modified date of a dynamic language source file that exists
file system).
[[dynamic-language-beans-inline]]
==== Inline Dynamic Language Source Files
@ -376,7 +361,6 @@ work using inline source. (See <<dynamic-language-scenarios-validators>> for suc @@ -376,7 +361,6 @@ work using inline source. (See <<dynamic-language-scenarios-validators>> for suc
example.)
[[dynamic-language-beans-ctor-injection]]
==== Understanding Constructor Injection in the Context of Dynamic-language-backed Beans
@ -408,7 +392,6 @@ does not work: @@ -408,7 +392,6 @@ does not work:
String message
String anotherMessage
}
----
@ -438,17 +421,6 @@ injection is the injection style favored by the overwhelming majority of develop @@ -438,17 +421,6 @@ injection is the injection style favored by the overwhelming majority of develop
This section describes how to use beans defined in Groovy in Spring.
.The Groovy library dependencies
****
The Groovy scripting support in Spring requires the following libraries to be on the
classpath of your application:
* `groovy-1.8.jar`
* `asm-3.2.jar`
* `antlr-2.7.7.jar`
****
The Groovy homepage includes the following description:
"`Groovy is an agile dynamic language for the Java 2 Platform that has many of the
@ -456,7 +428,7 @@ features that people like so much in languages like Python, Ruby and Smalltalk, @@ -456,7 +428,7 @@ features that people like so much in languages like Python, Ruby and Smalltalk,
them available to Java developers using a Java-like syntax.`"
If you have read this chapter straight from the top, you have already
<<dynamic-language-a-first-example,seen an example>> of a Groovy-dynamic-language-backed
<<dynamic-language-a-first-example, seen an example>> of a Groovy-dynamic-language-backed
bean. Now consider another example (again using an example from the Spring test suite):
[source,java,indent=0]
@ -467,7 +439,6 @@ bean. Now consider another example (again using an example from the Spring test @@ -467,7 +439,6 @@ bean. Now consider another example (again using an example from the Spring test
public interface Calculator {
int add(int x, int y);
}
----
@ -484,7 +455,6 @@ The following example implements the `Calculator` interface in Groovy: @@ -484,7 +455,6 @@ The following example implements the `Calculator` interface in Groovy:
int add(int x, int y) {
x + y
}
}
----
@ -520,15 +490,13 @@ Finally, the following small application exercises the preceding configuration: @@ -520,15 +490,13 @@ Finally, the following small application exercises the preceding configuration:
----
The resulting output from running the above program is (unsurprisingly) `10`.
(For more interesting examples,
see the dynamic language showcase project for a more complex example or see the examples
<<dynamic-language-scenarios>> later in this chapter).
You must not define more than one class per Groovy source file.
While this is perfectly legal in Groovy, it is (arguably) a bad practice. In the
interests of a consistent approach, you should (in the opinion of the Spring team) respect
the standard Java conventions of one (public) class per source file.
(For more interesting examples, see the dynamic language showcase project for a more
complex example or see the examples <<dynamic-language-scenarios>> later in this chapter).
You must not define more than one class per Groovy source file. While this is perfectly
legal in Groovy, it is (arguably) a bad practice. In the interests of a consistent
approach, you should (in the opinion of the Spring team) respect the standard Java
conventions of one (public) class per source file.
[[dynamic-language-beans-groovy-customizer]]
@ -549,11 +517,11 @@ shows the `GroovyObjectCustomizer` interface definition: @@ -549,11 +517,11 @@ shows the `GroovyObjectCustomizer` interface definition:
}
----
The Spring Framework instantiates an instance of your Groovy-backed bean and
then passes the created `GroovyObject` to the specified `GroovyObjectCustomizer` (if one
The Spring Framework instantiates an instance of your Groovy-backed bean and then
passes the created `GroovyObject` to the specified `GroovyObjectCustomizer` (if one
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:
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"]
@ -577,8 +545,8 @@ and the following example shows how to do so: @@ -577,8 +545,8 @@ 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
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
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]
@ -621,15 +589,6 @@ in the same place as Spring's `GroovyObjectCustomizer`. @@ -621,15 +589,6 @@ in the same place as Spring's `GroovyObjectCustomizer`.
This section describes how to use BeanShell beans in Spring.
.The BeanShell library dependencies
****
The BeanShell scripting support in Spring requires the following libraries to be on the
classpath of your application:
* `bsh-2.0b4.jar`
****
The BeanShell homepage includes the following description: {JB}
"`BeanShell is a small, free, embeddable Java source interpreter with dynamic language
@ -639,12 +598,12 @@ closures like those in Perl and JavaScript.`" @@ -639,12 +598,12 @@ closures like those in Perl and JavaScript.`"
In contrast to Groovy, BeanShell-backed bean definitions require some (small) additional
configuration. The implementation of the BeanShell dynamic language support in Spring is
interesting, because Spring creates a JDK dynamic proxy
that implements all of the interfaces that are specified in the `script-interfaces`
attribute value of the `<lang:bsh>` element (this is why you must supply at least
one interface in the value of the attribute, and, consequently, program to interfaces
when you use BeanShell-backed beans). This means that every method call on a
BeanShell-backed object goes through the JDK dynamic proxy invocation mechanism.
interesting, because Spring creates a JDK dynamic proxy that implements all of the
interfaces that are specified in the `script-interfaces` attribute value of the
`<lang:bsh>` element (this is why you must supply at least one interface in the value
of the attribute, and, consequently, program to interfaces when you use BeanShell-backed
beans). This means that every method call on a BeanShell-backed object goes through the
JDK dynamic proxy invocation mechanism.
Now we can show a fully working example of using a BeanShell-based bean that implements
the `Messenger` interface that was defined earlier in this chapter. We again show the
@ -658,12 +617,11 @@ definition of the `Messenger` interface: @@ -658,12 +617,11 @@ definition of the `Messenger` interface:
public interface Messenger {
String getMessage();
}
----
The following example shows the BeanShell "`implementation`" (we use the term loosely here) 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"]
@ -679,8 +637,8 @@ The following example shows the BeanShell "`implementation`" (we use the term lo @@ -679,8 +637,8 @@ The following example shows the BeanShell "`implementation`" (we use the term lo
}
----
The following example shows the Spring XML that defines an "`instance`" of the above "`class`" (again,
we use these terms very loosely here):
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"]
@ -697,12 +655,13 @@ BeanShell-based beans. @@ -697,12 +655,13 @@ BeanShell-based beans.
[[dynamic-language-scenarios]]
== Scenarios
The possible scenarios where defining Spring managed beans in a scripting language would
be beneficial are many and varied. This section describes two possible use
cases for the dynamic language support in Spring.
be beneficial are many and varied. This section describes two possible use cases for the
dynamic language support in Spring.
@ -755,7 +714,6 @@ by using the Groovy dynamic language: @@ -755,7 +714,6 @@ by using the Groovy dynamic language:
HttpServletResponse httpServletResponse) {
return new ModelAndView("tell", "fortune", this.fortuneService.tellFortune())
}
}
----
@ -784,13 +742,12 @@ validation logic by editing and saving a simple text file. Any such changes is @@ -784,13 +742,12 @@ validation logic by editing and saving a simple text file. Any such changes is
(depending on the configuration) automatically reflected in the execution of a
running application and would not require the restart of an application.
NOTE: To effect the automatic "`pickup`" of any changes to
dynamic-language-backed beans, you have to enable the 'refreshable beans'
feature. See <<dynamic-language-refreshable-beans>> for a full and detailed treatment of
this feature.
NOTE: To effect the automatic "`pickup`" of any changes to dynamic-language-backed
beans, you have to enable the 'refreshable beans' feature. See
<<dynamic-language-refreshable-beans>> for a full and detailed treatment of this feature.
The following example shows a Spring `org.springframework.validation.Validator` implemented
by using the Groovy dynamic language (see <<core.adoc#validator,
The following example shows a Spring `org.springframework.validation.Validator`
implemented by using the Groovy dynamic language (see <<core.adoc#validator,
Validation using Spring’s Validator interface>> for a discussion of the
`Validator` interface):
@ -813,12 +770,12 @@ Validation using Spring’s Validator interface>> for a discussion of the @@ -813,12 +770,12 @@ Validation using Spring’s Validator interface>> for a discussion of the
}
errors.reject("whitespace", "Cannot be composed wholly of whitespace.")
}
}
----
[[dynamic-language-final-notes]]
== Additional Details
@ -832,14 +789,12 @@ This last section contains some additional details related to the dynamic langua @@ -832,14 +789,12 @@ This last section contains some additional details related to the dynamic langua
You can use the Spring AOP framework to advise scripted beans. The Spring AOP
framework actually is unaware that a bean that is being advised might be a scripted
bean, so all of the AOP use cases and functionality that you use (or aim to use)
work with scripted beans.
When you advise scripted beans, you cannot use class-based proxies. You must
use <<core.adoc#aop-proxying,interface-based proxies>>.
work with scripted beans. When you advise scripted beans, you cannot use class-based
proxies. You must use <<core.adoc#aop-proxying, interface-based proxies>>.
You are not limited to advising scripted beans. You can also write
aspects themselves in a supported dynamic language and use such beans to advise other
Spring beans. This really would be an advanced use of the dynamic language support
though.
You are not limited to advising scripted beans. You can also write aspects themselves
in a supported dynamic language and use such beans to advise other Spring beans.
This really would be an advanced use of the dynamic language support though.
@ -849,11 +804,11 @@ though. @@ -849,11 +804,11 @@ though.
In case it is not immediately obvious, scripted beans can be scoped in the same way as
any other bean. The `scope` attribute on the various `<lang:language/>` elements lets
you control the scope of the underlying scripted bean, as it does with a regular
bean. (The default scope is <<core.adoc#beans-factory-scopes-singleton,singleton>>, as it is
with "`regular`" beans.)
bean. (The default scope is <<core.adoc#beans-factory-scopes-singleton, singleton>>,
as it is with "`regular`" beans.)
The following example uses the `scope` attribute to define a Groovy bean scoped as
a <<core.adoc#beans-factory-scopes-prototype,prototype>>:
a <<core.adoc#beans-factory-scopes-prototype, prototype>>:
[source,xml,indent=0]
[subs="verbatim,quotes"]
@ -876,26 +831,24 @@ a <<core.adoc#beans-factory-scopes-prototype,prototype>>: @@ -876,26 +831,24 @@ a <<core.adoc#beans-factory-scopes-prototype,prototype>>:
</beans>
----
See <<core.adoc#beans-factory-scopes,Bean scopes>> in <<core.adoc#beans,The IoC container>>
See <<core.adoc#beans-factory-scopes, Bean Scopes>> in <<core.adoc#beans, The IoC Container>>
for a full discussion of the scoping support in the Spring Framework.
[[xsd-schemas-lang]]
=== The `lang` XML schema
The `lang` elements in Spring XML configuration deal with exposing objects that have been written
in a dynamic language (such as JRuby or Groovy) as beans in the Spring container.
The `lang` elements in Spring XML configuration deal with exposing objects that have been
written in a dynamic language (such as Groovy or BeanShell) as beans in the Spring container.
These elements (and the dynamic language support) are comprehensively covered in
<<integration.adoc#dynamic-language,Dynamic language support>>.
See that chapter for full details on this support and the `lang` elements.
<<integration.adoc#dynamic-language, Dynamic Language Support>>. See that chapter
for full details on this support and the `lang` elements.
To use the elements in the `lang` schema, you need to have
the following preamble at the top of your Spring XML configuration file. The text in the
following snippet references the correct schema so that the tags in the `lang` namespace
are available to you:
To use the elements in the `lang` schema, you need to have the following preamble at the
top of your Spring XML configuration file. The text in the 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"]
@ -914,12 +867,13 @@ are available to you: @@ -914,12 +867,13 @@ are available to you:
[[dynamic-language-resources]]
== Further Resources
The following links go to further resources about the various dynamic languages described in
this chapter:
The following links go to further resources about the various dynamic languages referenced
in this chapter:
* The http://jruby.org/[JRuby] homepage
* The http://www.groovy-lang.org/[Groovy] homepage
* The http://www.beanshell.org/[BeanShell] homepage
* The http://jruby.org/[JRuby] homepage

2
src/docs/asciidoc/languages/groovy.adoc

@ -7,7 +7,7 @@ existing Java application. @@ -7,7 +7,7 @@ existing Java application.
The Spring Framework provides a dedicated `ApplicationContext` that supports a Groovy-based
Bean Definition DSL. For more details, see
<<core.adoc#groovy-bean-definition-dsl,The Groovy Bean Definition DSL>>.
<<core.adoc#groovy-bean-definition-dsl, The Groovy Bean Definition DSL>>.
Further support for Groovy, including beans written in Groovy, refreshable script beans,
and more is available in <<dynamic-language>>.

157
src/docs/asciidoc/languages/kotlin.adoc

@ -1,35 +1,37 @@ @@ -1,35 +1,37 @@
[[kotlin]]
= Kotlin
https://kotlinlang.org[Kotlin] is a statically typed language that targets the JVM (and other platforms),
which allows writing concise and elegant code while providing very good
https://kotlinlang.org/docs/reference/java-interop.html[interoperability] with
existing libraries written in Java.
https://kotlinlang.org[Kotlin] is a statically typed language that targets the JVM
(and other platforms), which allows writing concise and elegant code while providing
very good https://kotlinlang.org/docs/reference/java-interop.html[interoperability]
with existing libraries written in Java.
The Spring Framework provides first-class support for Kotlin that lets developers write
Kotlin applications almost as if the Spring Framework were a native Kotlin framework.
The easiest way to learn about Spring and Kotlin is to follow
https://spring.io/guides/tutorials/spring-boot-kotlin/[this comprehensive tutorial]. Feel
free to join the #spring channel of http://slack.kotlinlang.org/[Kotlin Slack] or ask a
question with `spring` and `kotlin` as tags on
https://spring.io/guides/tutorials/spring-boot-kotlin/[this comprehensive tutorial].
Feel free to join the #spring channel of http://slack.kotlinlang.org/[Kotlin Slack]
or ask a question with `spring` and `kotlin` as tags on
https://stackoverflow.com/questions/tagged/spring+kotlin[Stackoverflow] if you need support.
[[kotlin-requirements]]
== Requirements
The Spring Framework supports Kotlin 1.3+ and requires
Spring Framework 5.2 supports Kotlin 1.3+ and requires
https://bintray.com/bintray/jcenter/org.jetbrains.kotlin%3Akotlin-stdlib[`kotlin-stdlib`]
(or one of its variants, such as
https://bintray.com/bintray/jcenter/org.jetbrains.kotlin%3Akotlin-stdlib-jdk8[`kotlin-stdlib-jdk8`])
(or one of its variants, such as https://bintray.com/bintray/jcenter/org.jetbrains.kotlin%3Akotlin-stdlib-jre8[`kotlin-stdlib-jre8`]
or https://bintray.com/bintray/jcenter/org.jetbrains.kotlin%3Akotlin-stdlib-jdk8[`kotlin-stdlib-jdk8`])
and https://bintray.com/bintray/jcenter/org.jetbrains.kotlin%3Akotlin-reflect[`kotlin-reflect`]
to be present on the classpath. They are provided by default if you bootstrap a Kotlin project on
https://start.spring.io/#!language=kotlin[start.spring.io].
[[kotlin-extensions]]
== Extensions
@ -75,6 +77,7 @@ for shorter syntax. @@ -75,6 +77,7 @@ for shorter syntax.
[[kotlin-null-safety]]
== Null-safety
@ -86,7 +89,7 @@ declarations and expressing "`value or no value`" semantics without paying the c @@ -86,7 +89,7 @@ declarations and expressing "`value or no value`" semantics without paying the c
http://www.baeldung.com/kotlin-null-safety[comprehensive guide to Kotlin null-safety].)
Although Java does not let you express null-safety in its type-system, the Spring Framework
provides <<core#null-safety,null-safety of the whole Spring Framework API>>
provides <<core#null-safety, null-safety of the whole Spring Framework API>>
via tooling-friendly annotations declared in the `org.springframework.lang` package.
By default, types from Java APIs used in Kotlin are recognized as
https://kotlinlang.org/docs/reference/java-interop.html#null-safety-and-platform-types[platform types],
@ -112,6 +115,7 @@ for up-to-date information. @@ -112,6 +115,7 @@ for up-to-date information.
[[kotlin-classes-interfaces]]
== Classes and Interfaces
@ -134,6 +138,7 @@ since the later requires a reference to the outer class. @@ -134,6 +138,7 @@ since the later requires a reference to the outer class.
[[kotlin-annotations]]
== Annotations
@ -162,6 +167,7 @@ https://stackoverflow.com/a/35853200/1092077[this Stack Overflow response]. @@ -162,6 +167,7 @@ https://stackoverflow.com/a/35853200/1092077[this Stack Overflow response].
[[kotlin-bean-definition-dsl]]
== Bean Definition DSL
@ -251,11 +257,12 @@ for more details and up-to-date information. @@ -251,11 +257,12 @@ for more details and up-to-date information.
[[kotlin-web]]
== Web
=== WebFlux router DSL
=== WebFlux Router DSL
Spring Framework comes with a Kotlin router DSL available in 2 flavors:
@ -292,6 +299,8 @@ depending on dynamic data (for example, from a database). @@ -292,6 +299,8 @@ depending on dynamic data (for example, from a database).
See https://github.com/mixitconf/mixit/tree/dafd5ccc92dfab6d9c306fcb60b28921a1ccbf79/src/main/kotlin/mixit/web/routes[MiXiT project routes]
for a concrete example.
=== Coroutines
As of Spring Framework 5.2, https://kotlinlang.org/docs/reference/coroutines-overview.html[Coroutines] support
@ -326,6 +335,8 @@ class UserHandler(builder: WebClient.Builder) { @@ -326,6 +335,8 @@ class UserHandler(builder: WebClient.Builder) {
Read this blog post about https://medium.com/@elizarov/structured-concurrency-722d765aa952[structured concurrency]
to understand how to run code concurrently with Coroutines.
=== MockMvc DSL
A Kotlin DSL is provided via `MockMvc` Kotlin extensions in order to provide a more idiomatic Kotlin API and to allow
@ -351,6 +362,8 @@ mockMvc.get("/person/{name}", "Lee") { @@ -351,6 +362,8 @@ mockMvc.get("/person/{name}", "Lee") {
}
----
=== Kotlin Script Templates
As of version 4.3, Spring Framework provides a
@ -391,27 +404,27 @@ See the https://github.com/sdeleuze/kotlin-script-templating[kotlin-script-templ @@ -391,27 +404,27 @@ See the https://github.com/sdeleuze/kotlin-script-templating[kotlin-script-templ
project for more details.
[[kotlin-spring-projects-in-kotlin]]
== Spring Projects in Kotlin
This section provides some specific hints and recommendations worth
for developing Spring projects in Kotlin.
This section provides some specific hints and recommendations worth for developing Spring projects
in Kotlin.
=== Final by Default
By default, https://discuss.kotlinlang.org/t/classes-final-by-default/166[all classes in Kotlin are `final`].
The `open` modifier on a class is the opposite of Java's `final`: It allows others to
inherit from this class. This also applies to member functions, in that they need to be marked as `open` to
be overridden.
While Kotlin's JVM-friendly design is generally frictionless with Spring,
this specific Kotlin feature can prevent the application from starting, if this fact is not taken into
consideration. This is because Spring beans
(such as `@Configuration` classes which need to be inherited at runtime for technical reasons) are normally proxied by CGLIB.
The workaround was to add an `open` keyword on each class and member
function of Spring beans that are proxied by CGLIB (such as `@Configuration` classes), which can
The `open` modifier on a class is the opposite of Java's `final`: It allows others to inherit from this
class. This also applies to member functions, in that they need to be marked as `open` to be overridden.
While Kotlin's JVM-friendly design is generally frictionless with Spring, this specific Kotlin feature
can prevent the application from starting, if this fact is not taken into consideration. This is because
Spring beans (such as `@Configuration` classes which need to be inherited at runtime for technical
reasons) are normally proxied by CGLIB. The workaround was to add an `open` keyword on each class and
member function of Spring beans that are proxied by CGLIB (such as `@Configuration` classes), which can
quickly become painful and is against the Kotlin principle of keeping code concise and predictable.
Fortunately, Kotlin now provides a
@ -474,15 +487,16 @@ the https://kotlinlang.org/docs/reference/compiler-plugins.html#how-to-use-no-ar @@ -474,15 +487,16 @@ the https://kotlinlang.org/docs/reference/compiler-plugins.html#how-to-use-no-ar
plugin.
NOTE: As of the Kay release train, Spring Data supports Kotlin immutable class instances and
does not require the `kotlin-noarg` plugin if the module uses Spring Data object
mappings (such as MongoDB, Redis, Cassandra, and others).
does not require the `kotlin-noarg` plugin if the module uses Spring Data object mappings
(such as MongoDB, Redis, Cassandra, and others).
=== Injecting Dependencies
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:
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]
----
@ -493,9 +507,9 @@ https://kotlinlang.org/docs/reference/properties.html[properties], as the follow @@ -493,9 +507,9 @@ https://kotlinlang.org/docs/reference/properties.html[properties], as the follow
)
----
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
explicit `@Autowired constructor` in the example shown above.
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 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:
@ -518,13 +532,14 @@ as the following example shows: @@ -518,13 +532,14 @@ as the following example shows:
=== Injecting Configuration Properties
In Java, you can inject configuration properties by using annotations (such as `@Value("${property}")`).
However, in Kotlin, `$` is a reserved character that is used for https://kotlinlang.org/docs/reference/idioms.html#string-interpolation[string interpolation].
However, in Kotlin, `$` is a reserved character that is used for
https://kotlinlang.org/docs/reference/idioms.html#string-interpolation[string interpolation].
Therefore, if you wish to use the `@Value` annotation in Kotlin, you need to escape the `$`
character by writing `@Value("\${property}")`.
As an alternative, you can customize the properties placeholder prefix by declaring
the following configuration beans:
As an alternative, you can customize the properties placeholder prefix by declaring the
following configuration beans:
[source,kotlin,indent=0]
----
@ -534,8 +549,8 @@ the following configuration beans: @@ -534,8 +549,8 @@ the following configuration beans:
}
----
You can customize existing code (such as Spring Boot actuators or `@LocalServerPort`) that uses the `${...}` syntax,
with configuration beans, as the following example shows:
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]
----
@ -551,35 +566,38 @@ with configuration beans, as the following example shows: @@ -551,35 +566,38 @@ with configuration beans, as the following example shows:
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`]
instead of `@Value` annotations. However, currently, this only works with `lateinit` or nullable `var`
properties (we recommended the former), since immutable classes initialized by
constructors are not yet supported.
See these issues about https://github.com/spring-projects/spring-boot/issues/8762[`@ConfigurationProperties` binding for immutable POJOs]
instead of `@Value` annotations. However, currently, this only works with `lateinit` or
nullable `var` properties (we recommended the former), since immutable classes initialized
by constructors are not yet supported. See these issues about
https://github.com/spring-projects/spring-boot/issues/8762[`@ConfigurationProperties` binding for immutable POJOs]
and https://github.com/spring-projects/spring-boot/issues/1254[`@ConfigurationProperties` binding on interfaces]
for more details.
=== Checked Exceptions
Java and https://kotlinlang.org/docs/reference/exceptions.html[Kotlin exception handling] are pretty close, with the main
difference being that Kotlin treats all exceptions as unchecked exceptions. However, when using proxied objects
(for example classes or methods annotated with `@Transactional`), checked exceptions thrown will be wrapped by default in
Java and https://kotlinlang.org/docs/reference/exceptions.html[Kotlin exception handling]
are pretty close, with the main difference being that Kotlin treats all exceptions as
unchecked exceptions. However, when using proxied objects (for example classes or methods
annotated with `@Transactional`), checked exceptions thrown will be wrapped by default in
an `UndeclaredThrowableException`.
To get the original exception thrown like in Java, methods should be annotated with https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/-throws/index.html[`@Throws`]
To get the original exception thrown like in Java, methods should be annotated with
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/-throws/index.html[`@Throws`]
to specify explicitly the checked exceptions thrown (for example `@Throws(IOException::class)`).
=== Annotation Array Attributes
Kotlin annotations are mostly similar to Java annotations, but array attributes (which are
extensively used in Spring) behave differently. As explained in
https://kotlinlang.org/docs/reference/annotations.html[Kotlin documentation]
you can omit the `value` attribute name, unlike other attributes, and
specify it as a `vararg` parameter.
https://kotlinlang.org/docs/reference/annotations.html[Kotlin documentation] you can omit
the `value` attribute name, unlike other attributes, and 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:
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]
----
@ -598,14 +616,14 @@ of the most widely used Spring annotations) as an example. This Java annotation @@ -598,14 +616,14 @@ 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
annotation array attribute, and it is automatically converted to an array.
and method. In Java, you can specify a single value for the annotation array attribute,
and it is automatically converted to an array.
That is why one can write
`@RequestMapping(value = "/toys", method = RequestMethod.GET)` or
`@RequestMapping(path = "/toys", method = RequestMethod.GET)`.
However, in Kotlin 1.2+, you must write `@RequestMapping("/toys", method = [RequestMethod.GET])`
However, in Kotlin, you must write `@RequestMapping("/toys", method = [RequestMethod.GET])`
or `@RequestMapping(path = ["/toys"], method = [RequestMethod.GET])` (square brackets need
to be specified with named array attributes).
@ -619,14 +637,16 @@ all HTTP methods will be matched, not only the `GET` one. @@ -619,14 +637,16 @@ all HTTP methods will be matched, not only the `GET` one.
=== Testing
This section addresses testing with the combination of Kotlin and Spring Framework. The recommended testing framework
is https://junit.org/junit5/[JUnit 5], as well as https://mockk.io/[Mockk] for mocking.
This section addresses testing with the combination of Kotlin and Spring Framework.
The recommended testing framework is https://junit.org/junit5/[JUnit 5], as well as
https://mockk.io/[Mockk] for mocking.
==== Constructor injection
As described in the <<testing#testcontext-junit-jupiter-di#spring-web-reactive,dedicated section>>, JUnit 5 allows
constructor injection of beans which is pretty useful with Kotlin in order to use `val` instead of `lateinit var`.
As described in the <<testing#testcontext-junit-jupiter-di#spring-web-reactive, dedicated section>>,
JUnit 5 allows constructor injection of beans which is pretty useful with Kotlin
in order to use `val` instead of `lateinit var`.
====
@ -661,12 +681,11 @@ class OrderServiceIntegrationTests @Autowired constructor( @@ -661,12 +681,11 @@ class OrderServiceIntegrationTests @Autowired constructor(
Kotlin lets you specify meaningful test function names between backticks (```).
As of JUnit 5, Kotlin test classes can use the `@TestInstance(TestInstance.Lifecycle.PER_CLASS)`
annotation to enable a single instantiation of test classes, which allows the use of `@BeforeAll` and `@AfterAll`
annotations on non-static methods, which is a good fit for Kotlin.
annotation to enable a single instantiation of test classes, which allows the use of `@BeforeAll`
and `@AfterAll` annotations on non-static methods, which is a good fit for Kotlin.
You can also change the default behavior to `PER_CLASS` thanks to a
`junit-platform.properties` file with a
`junit.jupiter.testinstance.lifecycle.default = per_class` property.
You can also change the default behavior to `PER_CLASS` thanks to a `junit-platform.properties`
file with a `junit.jupiter.testinstance.lifecycle.default = per_class` property.
The following example demonstrates `@BeforeAll` and `@AfterAll` annotations on non-static methods:
@ -701,7 +720,6 @@ class IntegrationTests { @@ -701,7 +720,6 @@ class IntegrationTests {
----
==== Specification-like Tests
You can create specification-like tests with JUnit 5 and Kotlin.
@ -732,18 +750,18 @@ class SpecificationLikeTests { @@ -732,18 +750,18 @@ class SpecificationLikeTests {
----
[[kotlin-webtestclient-issue]]
==== `WebTestClient` Type Inference Issue in Kotlin
Due to a https://youtrack.jetbrains.com/issue/KT-5464[type inference issue], you must
use the Kotlin `expectBody` extension (such as `.expectBody<String>().isEqualTo("toys")`), since it
provides a workaround for the Kotlin issue with the Java API.
use the Kotlin `expectBody` extension (such as `.expectBody<String>().isEqualTo("toys")`),
since it provides a workaround for the Kotlin issue with the Java API.
See also the related https://jira.spring.io/browse/SPR-16057[SPR-16057] issue.
[[kotlin-getting-started]]
== Getting Started
@ -751,16 +769,18 @@ The easiest way to learn how to build a Spring application with Kotlin is to fol @@ -751,16 +769,18 @@ The easiest way to learn how to build a Spring application with Kotlin is to fol
https://spring.io/guides/tutorials/spring-boot-kotlin/[the dedicated tutorial].
=== `start.spring.io`
The easiest way to start a new Spring Framework 5 project in Kotlin is to create a new Spring
Boot 2 project on https://start.spring.io/#!language=kotlin[start.spring.io].
=== Choosing the Web Flavor
Spring Framework now comes with two different web stacks: <<web#mvc,Spring MVC>> and
<<web-reactive#spring-web-reactive,Spring WebFlux>>.
Spring Framework now comes with two different web stacks: <<web#mvc, Spring MVC>> and
<<web-reactive#spring-web-reactive, Spring WebFlux>>.
Spring WebFlux is recommended if you want to create applications that will deal with latency,
long-lived connections, streaming scenarios or if you want to use the web functional
@ -771,6 +791,7 @@ MVC and its annotation-based programming model is the recommended choice. @@ -771,6 +791,7 @@ MVC and its annotation-based programming model is the recommended choice.
[[kotlin-resources]]
== Resources
@ -785,6 +806,7 @@ Kotlin and the Spring Framework: @@ -785,6 +806,7 @@ Kotlin and the Spring Framework:
* https://kotlin.link/[Awesome Kotlin]
=== Examples
The following Github projects offer examples that you can learn from and possibly even extend:
@ -819,4 +841,3 @@ The following list categorizes the pending issues related to Spring and Kotlin s @@ -819,4 +841,3 @@ The following list categorizes the pending issues related to Spring and Kotlin s
** https://youtrack.jetbrains.com/issue/KT-14984[Impossible to pass not all SAM argument as function]
** https://youtrack.jetbrains.com/issue/KT-15125[Support JSR 223 bindings directly via script variables]
** https://youtrack.jetbrains.com/issue/KT-6653[Kotlin properties do not override Java-style getters and setters]

6
src/docs/asciidoc/overview.adoc

@ -7,8 +7,8 @@ @@ -7,8 +7,8 @@
Spring makes it easy to create Java enterprise applications. It provides everything you
need to embrace the Java language in an enterprise environment, with support for Groovy
and Kotlin as alternative languages on the JVM, and with the flexibility to create many
kinds of architectures depending on an application's needs. As of Spring Framework 5.0,
Spring requires JDK 8+ (Java SE 8+) and provides out-of-the-box support for JDK 9 already.
kinds of architectures depending on an application's needs. As of Spring Framework 5.1,
Spring requires JDK 8+ (Java SE 8+) and provides out-of-the-box support for JDK 11 LTS.
Spring supports a wide range of application scenarios. In a large enterprise, applications
often exist for a long time and have to run on a JDK and application server whose upgrade
@ -44,7 +44,7 @@ A note about modules: Spring's framework jars allow for deployment to JDK 9's mo @@ -44,7 +44,7 @@ A note about modules: Spring's framework jars allow for deployment to JDK 9's mo
"Automatic-Module-Name" manifest entries which define stable language-level module names
("spring.core", "spring.context" etc) independent from jar artifact names (the jars follow
the same naming pattern with "-" instead of ".", e.g. "spring-core" and "spring-context").
Of course, Spring's framework jars keep working fine on the classpath on both JDK 8 and 9.
Of course, Spring's framework jars keep working fine on the classpath on both JDK 8 and 9+.

27
src/docs/asciidoc/testing-webtestclient.adoc

@ -4,10 +4,10 @@ @@ -4,10 +4,10 @@
`WebTestClient` is a thin shell around <<web-reactive.adoc#webflux-client, WebClient>>,
using it to perform requests and exposing a dedicated, fluent API for verifying responses.
`WebTestClient` binds to a WebFlux application by using a
<<testing.adoc#mock-objects-web-reactive,mock request and response>>, or it can test any
<<testing.adoc#mock-objects-web-reactive, mock request and response>>, or it can test any
web server over an HTTP connection.
TIP: Kotlin users: See <<languages.adoc#kotlin-webtestclient-issue,this section>>
TIP: Kotlin users: See <<languages.adoc#kotlin-webtestclient-issue, this section>>
related to use of the `WebTestClient`.
@ -33,8 +33,8 @@ The following example shows how to create a server setup to test one `@Controlle @@ -33,8 +33,8 @@ The following example shows how to create a server setup to test one `@Controlle
client = WebTestClient.bindToController(new TestController()).build();
----
The preceding example loads the <<web-reactive.adoc#webflux-config,WebFlux Java configuration>> and
registers the given controller. The resulting WebFlux application is tested
The preceding example loads the <<web-reactive.adoc#webflux-config, WebFlux Java configuration>>
and registers the given controller. The resulting WebFlux application is tested
without an HTTP server by using mock request and response objects. There are more methods
on the builder to customize the default WebFlux Java configuration.
@ -44,7 +44,7 @@ on the builder to customize the default WebFlux Java configuration. @@ -44,7 +44,7 @@ on the builder to customize the default WebFlux Java configuration.
=== Bind to Router Function
The following example shows how to set up a server from a
<<web-reactive.adoc#webflux-fn,RouterFunction>>:
<<web-reactive.adoc#webflux-fn, RouterFunction>>:
[source,java,intent=0]
[subs="verbatim,quotes"]
@ -88,11 +88,10 @@ some subset of it: @@ -88,11 +88,10 @@ some subset of it:
<2> Inject the configuration
<3> Create the `WebTestClient`
Internally, the configuration is passed to `WebHttpHandlerBuilder` to set up
the request processing chain. See
<<web-reactive.adoc#webflux-web-handler-api,WebHandler API>> for more details. The
resulting WebFlux application is tested without an HTTP server by using mock request
and response objects.
Internally, the configuration is passed to `WebHttpHandlerBuilder` to set up the request
processing chain. See <<web-reactive.adoc#webflux-web-handler-api, WebHandler API>> for
more details. The resulting WebFlux application is tested without an HTTP server by
using mock request and response objects.
@ -132,7 +131,7 @@ are readily available following `bindToServer`. For all others, you need to use @@ -132,7 +131,7 @@ are readily available following `bindToServer`. For all others, you need to use
[[webtestclient-tests]]
== Writing Tests
`WebTestClient` provides an API identical to <<web-reactive.adoc#webflux-client,WebClient>>
`WebTestClient` provides an API identical to <<web-reactive.adoc#webflux-client, WebClient>>
up to the point of performing a request by using `exchange()`. What follows after
`exchange()` is a chained API workflow to verify responses.
@ -296,8 +295,8 @@ from the `reactor-test` module to do that, as the following example shows: @@ -296,8 +295,8 @@ from the `reactor-test` module to do that, as the following example shows:
[[webtestclient-request-body]]
=== Request Body
When it comes to building requests, the `WebTestClient` offers an API identical to the
`WebClient`, and the implementation is mostly a simple pass-through. See
the <<web-reactive.adoc#webflux-client-body,WebClient documentation>> for examples on
When it comes to building requests, the `WebTestClient` offers an API identical to
the `WebClient`, and the implementation is mostly a simple pass-through. See the
<<web-reactive.adoc#webflux-client-body, WebClient documentation>> for examples on
how to prepare a request with a body, including submitting form data, multipart requests,
and more.

211
src/docs/asciidoc/testing.adoc

@ -22,8 +22,8 @@ set up service locator registries and similar structures). @@ -22,8 +22,8 @@ set up service locator registries and similar structures).
== Introduction to Spring Testing
Testing is an integral part of enterprise software development. This chapter focuses on
the value added by the IoC principle to <<unit-testing,unit testing>> and on the benefits
of the Spring Framework's support for <<integration-testing,integration testing>>. (A
the value added by the IoC principle to <<unit-testing, unit testing>> and on the benefits
of the Spring Framework's support for <<integration-testing, integration testing>>. (A
thorough treatment of testing in the enterprise is beyond the scope of this reference
manual.)
@ -36,12 +36,12 @@ manual.) @@ -36,12 +36,12 @@ manual.)
Dependency injection should make your code less dependent on the container than it would
be with traditional Java EE development. The POJOs that make up your application should
be testable in JUnit or TestNG tests, with objects instantiated by using the `new`
operator, without Spring or any other container. You can use <<mock-objects,mock
objects>> (in conjunction with other valuable testing techniques) to test your code in
isolation. If you follow the architecture recommendations for Spring, the resulting clean
layering and componentization of your codebase facilitate easier unit testing. For
example, you can test service layer objects by stubbing or mocking DAO or repository
interfaces, without needing to access persistent data while running unit tests.
operator, without Spring or any other container. You can use <<mock-objects, mock objects>>
(in conjunction with other valuable testing techniques) to test your code in isolation.
If you follow the architecture recommendations for Spring, the resulting clean layering
and componentization of your codebase facilitate easier unit testing. For example,
you can test service layer objects by stubbing or mocking DAO or repository interfaces,
without needing to access persistent data while running unit tests.
True unit tests typically run extremely quickly, as there is no runtime infrastructure to
set up. Emphasizing true unit tests as part of your development methodology can boost
@ -68,8 +68,8 @@ Spring includes a number of packages dedicated to mocking: @@ -68,8 +68,8 @@ Spring includes a number of packages dedicated to mocking:
The `org.springframework.mock.env` package contains mock implementations of the
`Environment` and `PropertySource` abstractions (see
<<core.adoc#beans-definition-profiles,Bean Definition Profiles>>
and <<core.adoc#beans-property-source-abstraction,`PropertySource` Abstraction>>).
<<core.adoc#beans-definition-profiles, Bean Definition Profiles>>
and <<core.adoc#beans-property-source-abstraction, `PropertySource` Abstraction>>).
`MockEnvironment` and `MockPropertySource` are useful for developing
out-of-container tests for code that depends on environment-specific properties.
@ -177,8 +177,8 @@ TIP: To unit test your Spring MVC `Controller` classes as POJOs, use `ModelAndVi @@ -177,8 +177,8 @@ TIP: To unit test your Spring MVC `Controller` classes as POJOs, use `ModelAndVi
combined with `MockHttpServletRequest`, `MockHttpSession`, and so on from Spring's
<<mock-objects-servlet, Servlet API mocks>>. For thorough integration testing of your
Spring MVC and REST `Controller` classes in conjunction with your `WebApplicationContext`
configuration for Spring MVC, use the <<spring-mvc-test-framework,Spring MVC Test
Framework>> instead.
configuration for Spring MVC, use the
<<spring-mvc-test-framework, Spring MVC Test Framework>> instead.
@ -212,17 +212,17 @@ Doing so lets you test things such as: @@ -212,17 +212,17 @@ Doing so lets you test things such as:
The Spring Framework provides first-class support for integration testing in the
`spring-test` module. The name of the actual JAR file might include the release version
and might also be in the long `org.springframework.test` form, depending on where you get
it from (see the <<core.adoc#dependency-management,section on Dependency Management>> for
an explanation). This library includes the `org.springframework.test` package, which
it from (see the <<core.adoc#dependency-management, section on Dependency Management>>
for an explanation). This library includes the `org.springframework.test` package, which
contains valuable classes for integration testing with a Spring container. This testing
does not rely on an application server or other deployment environment. Such tests are
slower to run than unit tests but much faster than the equivalent Selenium tests or
remote tests that rely on deployment to an application server.
In Spring 2.5 and later, unit and integration testing support is provided in the form of
the annotation-driven <<testcontext-framework,Spring TestContext Framework>>. The
TestContext framework is agnostic of the actual testing framework in use, which allows
instrumentation of tests in various environments, including JUnit, TestNG, and others.
Unit and integration testing support is provided in the form of the annotation-driven
<<testcontext-framework, Spring TestContext Framework>>. The TestContext framework is
agnostic of the actual testing framework in use, which allows instrumentation of tests
in various environments, including JUnit, TestNG, and others.
@ -231,10 +231,10 @@ instrumentation of tests in various environments, including JUnit, TestNG, and o @@ -231,10 +231,10 @@ instrumentation of tests in various environments, including JUnit, TestNG, and o
Spring's integration testing support has the following primary goals:
* To manage <<testing-ctx-management,Spring IoC container caching>> between tests.
* To provide <<testing-fixture-di,Dependency Injection of test fixture instances>>.
* To provide <<testing-tx,transaction management>> appropriate to integration testing.
* To supply <<testing-support-classes,Spring-specific base classes>> that assist
* To manage <<testing-ctx-management, Spring IoC container caching>> between tests.
* To provide <<testing-fixture-di, Dependency Injection of test fixture instances>>.
* To provide <<testing-tx, transaction management>> appropriate to integration testing.
* To supply <<testing-support-classes, Spring-specific base classes>> that assist
developers in writing integration tests.
The next few sections describe each goal and provide links to implementation and
@ -294,8 +294,8 @@ integration tests that test the following areas: @@ -294,8 +294,8 @@ integration tests that test the following areas:
* The logic of the `HibernateTitleRepository`: Does the configured instance of this class
perform as anticipated?
See dependency injection of test fixtures with the <<testcontext-fixture-di,TestContext
framework>>.
See dependency injection of test fixtures with the
<<testcontext-fixture-di, TestContext framework>>.
[[testing-tx]]
@ -320,7 +320,7 @@ particular test to populate or modify the database), you can tell the TestContex @@ -320,7 +320,7 @@ particular test to populate or modify the database), you can tell the TestContex
framework to cause the transaction to commit instead of roll back by using the
<<integration-testing-annotations, `@Commit`>> annotation.
See transaction management with the <<testcontext-tx,TestContext framework>>.
See transaction management with the <<testcontext-tx, TestContext framework>>.
[[testing-support-classes]]
@ -337,12 +337,12 @@ which let you access: @@ -337,12 +337,12 @@ which let you access:
queries to confirm database state both before and after execution of database-related
application code, and Spring ensures that such queries run in the scope of the same
transaction as the application code. When used in conjunction with an ORM tool, be sure
to avoid <<testcontext-tx-false-positives,false positives>>.
to avoid <<testcontext-tx-false-positives, false positives>>.
In addition, you may want to create your own custom, application-wide superclass with
instance variables and methods specific to your project.
See support classes for the <<testcontext-support-classes,TestContext framework>>.
See support classes for the <<testcontext-support-classes, TestContext framework>>.
@ -364,15 +364,15 @@ methods. @@ -364,15 +364,15 @@ methods.
[TIP]
====
<<testcontext-support-classes-junit4,`AbstractTransactionalJUnit4SpringContextTests`>>
and <<testcontext-support-classes-testng,`AbstractTransactionalTestNGSpringContextTests`>>
<<testcontext-support-classes-junit4, `AbstractTransactionalJUnit4SpringContextTests`>>
and <<testcontext-support-classes-testng, `AbstractTransactionalTestNGSpringContextTests`>>
provide convenience methods that delegate to the aforementioned methods in
`JdbcTestUtils`.
The `spring-jdbc` module provides support for configuring and launching an embedded
database, which you can use in integration tests that interact with a database. For
details, see <<data-access.adoc#jdbc-embedded-database-support,Embedded Database
Support>> and <<data-access.adoc#jdbc-embedded-database-dao-testing,Testing Data Access
database, which you can use in integration tests that interact with a database.
For details, see <<data-access.adoc#jdbc-embedded-database-support, Embedded Database
Support>> and <<data-access.adoc#jdbc-embedded-database-dao-testing, Testing Data Access
Logic with an Embedded Database>>.
====
@ -381,8 +381,8 @@ Logic with an Embedded Database>>. @@ -381,8 +381,8 @@ Logic with an Embedded Database>>.
[[integration-testing-annotations]]
=== Annotations
This section covers annotations that you can use when you test Spring applications. It
includes the following topics:
This section covers annotations that you can use when you test Spring applications.
It includes the following topics:
* <<integration-testing-annotations-spring>>
* <<integration-testing-annotations-standard>>
@ -422,9 +422,8 @@ Spring's testing annotations include the following: @@ -422,9 +422,8 @@ Spring's testing annotations include the following:
`@BootstrapWith` is a class-level annotation that you can use to configure how the Spring
TestContext Framework is bootstrapped. Specifically, you can use `@BootstrapWith` to
specify a custom `TestContextBootstrapper`. See the
<<testcontext-bootstrapping,Bootstrapping the TestContext framework>> section for further
details.
specify a custom `TestContextBootstrapper`. See the section on
<<testcontext-bootstrapping, bootstrapping the TestContext framework>> for further details.
[[spring-testing-annotation-contextconfiguration]]
===== `@ContextConfiguration`
@ -635,7 +634,7 @@ be active: @@ -635,7 +634,7 @@ 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
programmatically by implementing a custom
<<testcontext-ctx-management-env-profiles-ActiveProfilesResolver,`ActiveProfilesResolver`>>
<<testcontext-ctx-management-env-profiles-ActiveProfilesResolver, `ActiveProfilesResolver`>>
and registering it by using the `resolver` attribute of `@ActiveProfiles`.
See <<testcontext-ctx-management-env-profiles>> and the
@ -1052,8 +1051,8 @@ you use test lifecycle callbacks from the underlying test framework instead of @@ -1052,8 +1051,8 @@ you use test lifecycle callbacks from the underlying test framework instead of
==== Spring JUnit 4 Testing Annotations
The following annotations are supported only when used in conjunction with the
<<testcontext-junit4-runner,SpringRunner>>, <<testcontext-junit4-rules,Spring's JUnit 4
rules>>, or <<testcontext-support-classes-junit4,Spring's JUnit 4 support classes>>:
<<testcontext-junit4-runner, SpringRunner>>, <<testcontext-junit4-rules, Spring's JUnit 4
rules>>, or <<testcontext-support-classes-junit4, Spring's JUnit 4 support classes>>:
* <<integration-testing-annotations-junit4-ifprofilevalue>>
* <<integration-testing-annotations-junit4-profilevaluesourceconfiguration>>
@ -1181,8 +1180,8 @@ how to use the `@Repeat` annotation: @@ -1181,8 +1180,8 @@ how to use the `@Repeat` annotation:
==== Spring JUnit Jupiter Testing Annotations
The following annotations are supported only when used in conjunction with the
<<testcontext-junit-jupiter-extension,`SpringExtension`>> and JUnit Jupiter (that is, the
programming model in JUnit 5):
<<testcontext-junit-jupiter-extension, `SpringExtension`>> and JUnit Jupiter
(that is, the programming model in JUnit 5):
* <<integration-testing-annotations-junit-jupiter-springjunitconfig>>
* <<integration-testing-annotations-junit-jupiter-springjunitwebconfig>>
@ -1289,11 +1288,10 @@ within that class are automatically enabled by default as well. @@ -1289,11 +1288,10 @@ within that class are automatically enabled by default as well.
Expressions can be any of the following:
* <<core.adoc#expressions,Spring Expression Language>> (SpEL) expression. For example:
* <<core.adoc#expressions, Spring Expression Language>> (SpEL) expression. For example:
`@EnabledIf("#{systemProperties['os.name'].toLowerCase().contains('mac')}")`
* Placeholder for a property available in the Spring
<<core.adoc#beans-environment,`Environment`>>. For example:
`@EnabledIf("${smoke.tests.enabled}")`
* Placeholder for a property available in the Spring <<core.adoc#beans-environment, `Environment`>>.
For example: `@EnabledIf("${smoke.tests.enabled}")`
* Text literal. For example: `@EnabledIf("true")`
Note, however, that a text literal that is not the result of dynamic resolution of a
@ -1326,11 +1324,10 @@ test methods within that class are automatically disabled as well. @@ -1326,11 +1324,10 @@ test methods within that class are automatically disabled as well.
Expressions can be any of the following:
* <<core.adoc#expressions,Spring Expression Language>> (SpEL) expression. For example:
* <<core.adoc#expressions, Spring Expression Language>> (SpEL) expression. For example:
`@DisabledIf("#{systemProperties['os.name'].toLowerCase().contains('mac')}")`
* Placeholder for a property available in the Spring
<<core.adoc#beans-environment,`Environment`>>. For example:
`@DisabledIf("${smoke.tests.disabled}")`
* Placeholder for a property available in the Spring <<core.adoc#beans-environment, `Environment`>>.
For example: `@DisabledIf("${smoke.tests.disabled}")`
* Text literal. For example: `@DisabledIf("true")`
Note, however, that a text literal that is not the result of dynamic resolution of a
@ -1357,11 +1354,11 @@ example, you can create a custom `@DisabledOnMac` annotation as follows: @@ -1357,11 +1354,11 @@ example, you can create a custom `@DisabledOnMac` annotation as follows:
==== Meta-Annotation Support for Testing
You can use most test-related annotations as
<<core.adoc#beans-meta-annotations,meta-annotations>> to create custom composed
<<core.adoc#beans-meta-annotations, meta-annotations>> to create custom composed
annotations and reduce configuration duplication across a test suite.
You can use each of the following as a meta-annotation in conjunction with the
<<testcontext-framework,TestContext framework>>.
<<testcontext-framework, TestContext framework>>.
* `@BootstrapWith`
* `@ContextConfiguration`
@ -1542,10 +1539,10 @@ required to extend a particular class hierarchy, such as the `abstract` support @@ -1542,10 +1539,10 @@ required to extend a particular class hierarchy, such as the `abstract` support
The following section provides an overview of the internals of the TestContext framework.
If you are interested only in using the framework and are not interested in extending it
with your own custom listeners or custom loaders, feel free to go directly to the
configuration (<<testcontext-ctx-management,context management>>,
<<testcontext-fixture-di,dependency injection>>, <<testcontext-tx,transaction
management>>), <<testcontext-support-classes,support classes>>, and
<<integration-testing-annotations,annotation support>> sections.
configuration (<<testcontext-ctx-management, context management>>,
<<testcontext-fixture-di, dependency injection>>, <<testcontext-tx,transaction
management>>), <<testcontext-support-classes, support classes>>, and
<<integration-testing-annotations, annotation support>> sections.
[[testcontext-key-abstractions]]
@ -1586,24 +1583,22 @@ responsible for managing a single `TestContext` and signaling events to each reg @@ -1586,24 +1583,22 @@ responsible for managing a single `TestContext` and signaling events to each reg
===== `TestExecutionListener`
`TestExecutionListener` defines the API for reacting to test-execution events published
by the `TestContextManager` with which the listener is registered. See
<<testcontext-tel-config>>.
`TestExecutionListener` defines the API for reacting to test-execution events published by
the `TestContextManager` with which the listener is registered. See <<testcontext-tel-config>>.
===== Context Loaders
`ContextLoader` is a strategy interface that was introduced in Spring 2.5 for loading an
`ApplicationContext` for an integration test managed by the Spring TestContext Framework.
You should implement `SmartContextLoader` instead of this interface to provide support
for annotated classes, active bean definition profiles, test property sources, context
hierarchies, and `WebApplicationContext` support.
`ContextLoader` is a strategy interface for loading an `ApplicationContext` for an
integration test managed by the Spring TestContext Framework. You should implement
`SmartContextLoader` instead of this interface to provide support for annotated classes,
active bean definition profiles, test property sources, context hierarchies, and
`WebApplicationContext` support.
`SmartContextLoader` is an extension of the `ContextLoader` interface introduced in
Spring 3.1. The `SmartContextLoader` SPI supersedes the `ContextLoader` SPI that was
introduced in Spring 2.5. Specifically, a `SmartContextLoader` can choose to process
resource locations, annotated classes, or context initializers. Furthermore, a
`SmartContextLoader` can set active bean definition profiles and test property sources in
the context that it loads.
Spring 3.1, superseding the original minimal `ContextLoader` SPI. Specifically, a
`SmartContextLoader` can choose to process resource locations, annotated classes,
or context initializers. Furthermore, a `SmartContextLoader` can set active bean
definition profiles and test property sources in the context that it loads.
Spring provides the following implementations:
@ -1684,7 +1679,7 @@ by default, exactly in the following order: @@ -1684,7 +1679,7 @@ by default, exactly in the following order:
You can register custom `TestExecutionListener` implementations for a test class
and its subclasses by using the `@TestExecutionListeners` annotation.
See <<integration-testing-annotations,annotation support>> and the javadoc for
See <<integration-testing-annotations, annotation support>> and the javadoc for
{api-spring-framework}/test/context/TestExecutionListeners.html[`@TestExecutionListeners`]
for details and examples.
@ -1709,7 +1704,7 @@ file. @@ -1709,7 +1704,7 @@ file.
===== Ordering `TestExecutionListener` Implementations
When the TestContext framework discovers default `TestExecutionListener` implementations
through the <<testcontext-tel-config-automatic-discovery,aforementioned>>
through the <<testcontext-tel-config-automatic-discovery, aforementioned>>
`SpringFactoriesLoader` mechanism, the instantiated listeners are sorted by using
Spring's `AnnotationAwareOrderComparator`, which honors Spring's `Ordered` interface and
`@Order` annotation for ordering. `AbstractTestExecutionListener` and all default
@ -1751,8 +1746,8 @@ which listeners are registered by default. Moreover, the set of default listener @@ -1751,8 +1746,8 @@ which listeners are registered by default. Moreover, the set of default listener
change from release to release -- for example, `SqlScriptsTestExecutionListener` was
introduced in Spring Framework 4.1, and `DirtiesContextBeforeModesTestExecutionListener`
was introduced in Spring Framework 4.2. Furthermore, third-party frameworks like Spring
Security register their own default `TestExecutionListener` implementations by using the
aforementioned <<testcontext-tel-config-automatic-discovery, automatic discovery
Security register their own default `TestExecutionListener` implementations by using
the aforementioned <<testcontext-tel-config-automatic-discovery, automatic discovery
mechanism>>.
To avoid having to be aware of and re-declare all default listeners, you can set the
@ -1842,8 +1837,8 @@ the web application context into your test, as follows: @@ -1842,8 +1837,8 @@ the web application context into your test, as follows:
Dependency injection by using `@Autowired` is provided by the
`DependencyInjectionTestExecutionListener`, which is configured by default (see
<<testcontext-fixture-di>>).
`DependencyInjectionTestExecutionListener`, which is configured by default
(see <<testcontext-fixture-di>>).
=====
Test classes that use the TestContext framework do not need to extend any particular
@ -1945,11 +1940,11 @@ example shows how to do so: @@ -1945,11 +1940,11 @@ example shows how to do so:
===== Context Configuration with Groovy Scripts
To load an `ApplicationContext` for your tests by using Groovy scripts that use the
<<core.adoc#groovy-bean-definition-dsl,Groovy Bean Definition DSL>>, you can annotate
<<core.adoc#groovy-bean-definition-dsl, Groovy Bean Definition DSL>>, you can annotate
your test class with `@ContextConfiguration` and configure the `locations` or `value`
attribute with an array that contains the resource locations of Groovy scripts. Resource
lookup semantics for Groovy scripts are the same as those described for
<<testcontext-ctx-management-xml,XML configuration files>>.
<<testcontext-ctx-management-xml, XML configuration files>>.
.Enabling Groovy script support
TIP: Support for using Groovy scripts to load an `ApplicationContext` in the Spring
@ -2899,7 +2894,7 @@ Contrast the comments in this example with the previous example. @@ -2899,7 +2894,7 @@ Contrast the comments in this example with the previous example.
--
To provide comprehensive web testing support, Spring 3.2 introduced a
`ServletTestExecutionListener` that is enabled by default. When testing against a
`WebApplicationContext`, this <<testcontext-key-abstractions,`TestExecutionListener`>>
`WebApplicationContext`, this <<testcontext-key-abstractions, `TestExecutionListener`>>
sets up default thread-local state by using Spring Web's `RequestContextHolder` before
each test method and creates a `MockHttpServletRequest`, a `MockHttpServletResponse`, and
a `ServletWebRequest` based on the base resource path configured with
@ -3176,7 +3171,7 @@ shows this configuration scenario: @@ -3176,7 +3171,7 @@ shows this configuration scenario:
NOTE: If you use `@DirtiesContext` in a test whose context is configured as part of a
context hierarchy, you can use the `hierarchyMode` flag to control how the context cache
is cleared. For further details, see the discussion of `@DirtiesContext` in
<<spring-testing-annotation-dirtiescontext,Spring Testing Annotations>> and the
<<spring-testing-annotation-dirtiescontext, Spring Testing Annotations>> and the
{api-spring-framework}/test/annotation/DirtiesContext.html[`@DirtiesContext`] javadoc.
--
@ -3186,12 +3181,12 @@ is cleared. For further details, see the discussion of `@DirtiesContext` in @@ -3186,12 +3181,12 @@ is cleared. For further details, see the discussion of `@DirtiesContext` in
When you use the `DependencyInjectionTestExecutionListener` (which is configured by
default), the dependencies of your test instances are injected from beans in the
application context that you configured with `@ContextConfiguration` or related
annotations. You may use setter injection, field injection, or both, depending on which
annotations you choose and whether you place them on setter methods or fields. If you are
using JUnit Jupiter you may also optionally use constructor injection (see
<<testcontext-junit-jupiter-di>>). For consistency with the annotation support introduced
in Spring 2.5 and 3.0, you can use Spring's `@Autowired` annotation or the `@Inject`
annotation from JSR 330 for field and setter injection.
annotations. You may use setter injection, field injection, or both, depending on
which annotations you choose and whether you place them on setter methods or fields.
If you are using JUnit Jupiter you may also optionally use constructor injection
(see <<testcontext-junit-jupiter-di>>). For consistency with Spring's annotation-based
injection support, you may also use Spring's `@Autowired` annotation or the `@Inject`
annotation from JSR-330 for field and setter injection.
TIP: For testing frameworks other than JUnit Jupiter, the TestContext framework does not
participate in instantiation of the test class. Thus, the use of `@Autowired` or
@ -3217,7 +3212,7 @@ dependency injection altogether by explicitly configuring your class with @@ -3217,7 +3212,7 @@ dependency injection altogether by explicitly configuring your class with
from the list of listeners.
Consider the scenario of testing a `HibernateTitleRepository` class, as outlined in the
<<integration-testing-goals,Goals>> section. The next two code listings demonstrate the
<<integration-testing-goals, Goals>> section. The next two code listings demonstrate the
use of `@Autowired` on fields and setter methods. The application context configuration
is presented after all sample code listings.
@ -3340,7 +3335,7 @@ bean by name there (as shown earlier, assuming that `myDataSource` is the bean ` @@ -3340,7 +3335,7 @@ bean by name there (as shown earlier, assuming that `myDataSource` is the bean `
[[testcontext-web-scoped-beans]]
==== Testing Request- and Session-scoped Beans
Spring has supported <<core#beans-factory-scopes-other,Request- and session-scoped
Spring has supported <<core#beans-factory-scopes-other, Request- and session-scoped
beans>> since the early years. Since Spring 3.2, you can test your request-scoped and
session-scoped beans by following these steps:
@ -3354,7 +3349,7 @@ session-scoped beans by following these steps: @@ -3354,7 +3349,7 @@ session-scoped beans by following these steps:
The next code snippet shows the XML configuration for a login use case. Note that the
`userService` bean has a dependency on a request-scoped `loginAction` bean. Also, the
`LoginAction` is instantiated by using <<core.adoc#expressions,SpEL expressions>> that
`LoginAction` is instantiated by using <<core.adoc#expressions, SpEL expressions>> that
retrieve the username and password from the current HTTP request. In our test, we want to
configure these request parameters through the mock managed by the TestContext framework.
The following listing shows the configuration for this use case:
@ -3488,7 +3483,7 @@ application code that is invoked by tests). Spring-managed and application-manag @@ -3488,7 +3483,7 @@ application code that is invoked by tests). Spring-managed and application-manag
transactions typically participate in test-managed transactions. However, you should use
caution if Spring-managed or application-managed transactions are configured with any
propagation type other than `REQUIRED` or `SUPPORTS` (see the discussion on
<<data-access.adoc#tx-propagation,transaction propagation>> for details).
<<data-access.adoc#tx-propagation, transaction propagation>> for details).
.Preemptive timeouts and test-managed transactions
[WARNING]
@ -3603,7 +3598,7 @@ database are automatically rolled back by the `TransactionalTestExecutionListene @@ -3603,7 +3598,7 @@ database are automatically rolled back by the `TransactionalTestExecutionListene
By default, test transactions will be automatically rolled back after completion of the
test; however, transactional commit and rollback behavior can be configured declaratively
via the `@Commit` and `@Rollback` annotations. See the corresponding entries in the
<<integration-testing-annotations,annotation support>> section for further details.
<<integration-testing-annotations, annotation support>> section for further details.
[[testcontext-tx-programmatic-tx-mgt]]
===== Programmatic Transaction Management
@ -3688,7 +3683,7 @@ algorithm used to look up a transaction manager in the test's `ApplicationContex @@ -3688,7 +3683,7 @@ algorithm used to look up a transaction manager in the test's `ApplicationContex
The following JUnit 4 based example displays a fictitious integration testing scenario
that highlights all transaction-related annotations. The example is not intended to
demonstrate best practices but rather to demonstrate how these annotations can be used.
See the <<integration-testing-annotations,annotation support>> section for further
See the <<integration-testing-annotations, annotation support>> section for further
information and configuration examples. <<testcontext-executing-sql-declaratively-tx,
Transaction management for `@Sql`>> contains an additional example that uses `@Sql` for
declarative SQL script execution with default transaction rollback semantics. The
@ -3871,7 +3866,7 @@ specifies SQL scripts for a test schema and test data, sets the statement separa @@ -3871,7 +3866,7 @@ specifies SQL scripts for a test schema and test data, sets the statement separa
Note that `ResourceDatabasePopulator` internally delegates to `ScriptUtils` for parsing
and running SQL scripts. Similarly, the `executeSqlScript(..)` methods in
<<testcontext-support-classes-junit4, `AbstractTransactionalJUnit4SpringContextTests`>>
and <<testcontext-support-classes-testng,`AbstractTransactionalTestNGSpringContextTests`>>
and <<testcontext-support-classes-testng, `AbstractTransactionalTestNGSpringContextTests`>>
internally use a `ResourceDatabasePopulator` to run SQL scripts. See the javadoc for the
various `executeSqlScript(..)` methods for further details.
@ -4128,8 +4123,8 @@ This may be due to the use of `@DirtiesContext` or due to automatic eviction fro @@ -4128,8 +4123,8 @@ This may be due to the use of `@DirtiesContext` or due to automatic eviction fro
`ContextCache`. If `@DirtiesContext` is the culprit, you either need to find a way to
avoid using `@DirtiesContext` or exclude such tests from parallel execution. If the
maximum size of the `ContextCache` has been exceeded, you can increase the maximum size
of the cache. See the discussion on <<testcontext-ctx-management-caching,context
caching>> for details.
of the cache. See the discussion on <<testcontext-ctx-management-caching, context caching>>
for details.
====
WARNING: Parallel test execution in the Spring TestContext Framework is only possible if
@ -4157,7 +4152,7 @@ loading application contexts, dependency injection of test instances, transactio @@ -4157,7 +4152,7 @@ loading application contexts, dependency injection of test instances, transactio
method execution, and so on. If you want to use the Spring TestContext Framework with an
alternative runner (such as JUnit 4's `Parameterized` runner) or third-party runners
(such as the `MockitoJUnitRunner`), you can, optionally, use
<<testcontext-junit4-rules,Spring's support for JUnit rules>> instead.
<<testcontext-junit4-rules, Spring's support for JUnit rules>> instead.
The following code listing shows the minimal requirements for configuring a test class to
run with the custom Spring `Runner`:
@ -4246,8 +4241,8 @@ extend `AbstractTransactionalJUnit4SpringContextTests`, you can access a `protec @@ -4246,8 +4241,8 @@ extend `AbstractTransactionalJUnit4SpringContextTests`, you can access a `protec
database. You can use such queries to confirm database state both before and after
running database-related application code, and Spring ensures that such queries run in
the scope of the same transaction as the application code. When used in conjunction with
an ORM tool, be sure to avoid <<testcontext-tx-false-positives,false positives>>. As
mentioned in <<integration-testing-support-jdbc>>,
an ORM tool, be sure to avoid <<testcontext-tx-false-positives, false positives>>.
As mentioned in <<integration-testing-support-jdbc>>,
`AbstractTransactionalJUnit4SpringContextTests` also provides convenience methods that
delegate to methods in `JdbcTestUtils` by using the aforementioned `jdbcTemplate`.
Furthermore, `AbstractTransactionalJUnit4SpringContextTests` provides an
@ -4255,7 +4250,7 @@ Furthermore, `AbstractTransactionalJUnit4SpringContextTests` provides an @@ -4255,7 +4250,7 @@ Furthermore, `AbstractTransactionalJUnit4SpringContextTests` provides an
TIP: These classes are a convenience for extension. If you do not want your test classes
to be tied to a Spring-specific class hierarchy, you can configure your own custom test
classes by using `@RunWith(SpringRunner.class)` or <<testcontext-junit4-rules,Spring's
classes by using `@RunWith(SpringRunner.class)` or <<testcontext-junit4-rules, Spring's
JUnit rules>>.
[[testcontext-junit-jupiter-extension]]
@ -4488,8 +4483,8 @@ extend `AbstractTransactionalTestNGSpringContextTests`, you can access a `protec @@ -4488,8 +4483,8 @@ extend `AbstractTransactionalTestNGSpringContextTests`, you can access a `protec
database. You can use such queries to confirm database state both before and after
running database-related application code, and Spring ensures that such queries run in
the scope of the same transaction as the application code. When used in conjunction with
an ORM tool, be sure to avoid <<testcontext-tx-false-positives,false positives>>. As
mentioned in <<integration-testing-support-jdbc>>,
an ORM tool, be sure to avoid <<testcontext-tx-false-positives, false positives>>.
As mentioned in <<integration-testing-support-jdbc>>,
`AbstractTransactionalTestNGSpringContextTests` also provides convenience methods that
delegate to methods in `JdbcTestUtils` by using the aforementioned `jdbcTemplate`.
Furthermore, `AbstractTransactionalTestNGSpringContextTests` provides an
@ -4540,7 +4535,7 @@ Furthermore, other controller methods such as `@InitBinder`, `@ModelAttribute`, @@ -4540,7 +4535,7 @@ Furthermore, other controller methods such as `@InitBinder`, `@ModelAttribute`,
The goal of Spring MVC Test is to provide an effective way to test controllers by
performing requests and generating responses through the actual `DispatcherServlet`.
Spring MVC Test builds on the familiar <<mock-objects-servlet,"`mock`" implementations of
Spring MVC Test builds on the familiar <<mock-objects-servlet, "`mock`" implementations of
the Servlet API>> available in the `spring-test` module. This allows performing requests
and generating responses without the need for running in a Servlet container. For the
most part, everything should work as it does at runtime with a few notable exceptions, as
@ -4589,7 +4584,7 @@ discussed later in this document. @@ -4589,7 +4584,7 @@ discussed later in this document.
[[spring-mvc-test-server-static-imports]]
===== Static Imports
The fluent API in the example from the <<spring-mvc-test-server,preceding section>>
The fluent API in the example from the <<spring-mvc-test-server, preceding section>>
requires a few static imports, such as `MockMvcRequestBuilders.{asterisk}`,
`MockMvcResultMatchers.{asterisk}`, and `MockMvcBuilders.{asterisk}`. An easy way to find
these classes is to search for types that match `MockMvc*`. If you use Eclipse or the
@ -5008,7 +5003,7 @@ full test coverage based on Spring MVC Test. @@ -5008,7 +5003,7 @@ full test coverage based on Spring MVC Test.
[[spring-mvc-test-server-htmlunit]]
==== HtmlUnit Integration
Spring provides integration between <<spring-mvc-test-server,MockMvc>> and
Spring provides integration between <<spring-mvc-test-server, MockMvc>> and
http://htmlunit.sourceforge.net/[HtmlUnit]. This simplifies performing end-to-end testing
when using HTML-based views. This integration lets you:
@ -5251,7 +5246,7 @@ assertions use the http://joel-costigliola.github.io/assertj/[AssertJ] library: @@ -5251,7 +5246,7 @@ assertions use the http://joel-costigliola.github.io/assertj/[AssertJ] library:
----
The preceding code improves on our
<<spring-mvc-test-server-htmlunit-mock-mvc-test,MockMvc test>> in a number of ways.
<<spring-mvc-test-server-htmlunit-mock-mvc-test, MockMvc test>> in a number of ways.
First, we no longer have to explicitly verify our form and then create a request that
looks like the form. Instead, we request the form, fill it out, and submit it, thereby
significantly reducing the overhead.
@ -5479,8 +5474,8 @@ We can then fill out the form and submit it to create a message, as follows: @@ -5479,8 +5474,8 @@ We can then fill out the form and submit it to create a message, as follows:
page.createMessage(ViewMessagePage.class, expectedSummary, expectedText);
----
This improves on the design of our <<spring-mvc-test-server-htmlunit-mah-usage,HtmlUnit
test>> by leveraging the Page Object Pattern. As we mentioned in
This improves on the design of our <<spring-mvc-test-server-htmlunit-mah-usage, HtmlUnit test>>
by leveraging the Page Object Pattern. As we mentioned in
<<spring-mvc-test-server-htmlunit-webdriver-why>>, we can use the Page Object Pattern
with HtmlUnit, but it is much easier with WebDriver. Consider the following
`CreateMessagePage` implementation:
@ -5656,7 +5651,7 @@ use http://www.gebish.org/[Geb] to make our tests even Groovy-er. @@ -5656,7 +5651,7 @@ use http://www.gebish.org/[Geb] to make our tests even Groovy-er.
====== Why Geb and MockMvc?
Geb is backed by WebDriver, so it offers many of the
<<spring-mvc-test-server-htmlunit-webdriver-why,same benefits>> that we get from
<<spring-mvc-test-server-htmlunit-webdriver-why, same benefits>> that we get from
WebDriver. However, Geb makes things even easier by taking care of some of the
boilerplate code for us.
@ -5710,7 +5705,7 @@ forwarded to the current page object. This removes a lot of the boilerplate code @@ -5710,7 +5705,7 @@ forwarded to the current page object. This removes a lot of the boilerplate code
needed when using WebDriver directly.
As with direct WebDriver usage, this improves on the design of our
<<spring-mvc-test-server-htmlunit-mah-usage,HtmlUnit test>> by using the Page Object
<<spring-mvc-test-server-htmlunit-mah-usage, HtmlUnit test>> by using the Page Object
Pattern. As mentioned previously, we can use the Page Object Pattern with HtmlUnit and
WebDriver, but it is even easier with Geb. Consider our new Groovy-based
`CreateMessagePage` implementation:

27
src/docs/asciidoc/web-reactive.adoc

@ -7,13 +7,13 @@ @@ -7,13 +7,13 @@
:tabsize: 4
:docinfo1:
This part of the documentation covers support for reactive-stack web applications built on a
http://www.reactive-streams.org/[Reactive Streams] API to run on non-blocking
This part of the documentation covers support for reactive-stack web applications built
on a http://www.reactive-streams.org/[Reactive Streams] API to run on non-blocking
servers, such as Netty, Undertow, and Servlet 3.1+ containers. Individual chapters cover
the <<webflux,Spring WebFlux>> framework,
the reactive <<webflux-client,`WebClient`>>, support for <<webflux-test, testing>>,
and <<webflux-reactive-libraries, reactive libraries>>. For Servlet-stack web applications, see
<<web.adoc#spring-web,Web on Servlet Stack>>.
the <<webflux, Spring WebFlux>> framework,
the reactive <<webflux-client, `WebClient`>>, support for <<webflux-test, testing>>,
and <<webflux-reactive-libraries, reactive libraries>>. For Servlet-stack web applications,
see <<web.adoc#spring-web, Web on Servlet Stack>>.
include::web/webflux.adoc[leveloffset=+1]
@ -26,13 +26,14 @@ include::web/webflux-websocket.adoc[leveloffset=+1] @@ -26,13 +26,14 @@ include::web/webflux-websocket.adoc[leveloffset=+1]
[[webflux-test]]
== Testing
[.small]#<<web.adoc#testing,Same in Spring MVC>>#
[.small]#<<web.adoc#testing, Same in Spring MVC>>#
The `spring-test` module provides mock implementations of `ServerHttpRequest`,
`ServerHttpResponse`, and `ServerWebExchange`.
See <<testing.adoc#mock-objects-web-reactive,Spring Web Reactive>> for a discussion of mock objects.
See <<testing.adoc#mock-objects-web-reactive, Spring Web Reactive>> for a
discussion of mock objects.
<<testing.adoc#webtestclient,`WebTestClient`>> builds on these mock request and
<<testing.adoc#webtestclient, `WebTestClient`>> builds on these mock request and
response objects to provide support for testing WebFlux applications without an HTTP
server. You can use the `WebTestClient` for end-to-end integration tests, too.
@ -53,10 +54,10 @@ server. You can use the `WebTestClient` for end-to-end integration tests, too. @@ -53,10 +54,10 @@ server. You can use the `WebTestClient` for end-to-end integration tests, too.
`spring-webflux` depends on `reactor-core` and uses it internally to compose asynchronous
logic and to provide Reactive Streams support. Generally, WebFlux APIs return `Flux` or
`Mono` (since those are used internally) and leniently accept any Reactive Streams
`Publisher` implementation as input. The use of `Flux` versus `Mono` is important, because it
helps to express cardinality -- for example, whether a single or multiple asynchronous values are
expected, and that can be essential for making decisions (for example, when encoding or
decoding HTTP messages).
`Publisher` implementation as input. The use of `Flux` versus `Mono` is important, because
it helps to express cardinality -- for example, whether a single or multiple asynchronous
values are expected, and that can be essential for making decisions (for example, when
encoding or decoding HTTP messages).
For annotated controllers, WebFlux transparently adapts to the reactive library chosen by
the application. This is done with the help of the

6
src/docs/asciidoc/web.adoc

@ -8,9 +8,9 @@ @@ -8,9 +8,9 @@
:docinfo1:
This part of the documentation covers support for Servlet-stack web applications built on the
Servlet API and deployed to Servlet containers. Individual chapters include <<mvc,Spring MVC>>,
<<mvc-view,View Technologies>>, <<mvc-cors,CORS Support>>, and <<websocket,WebSocket Support>>.
For reactive-stack web applications, see <<web-reactive.adoc#spring-web-reactive,Web on Reactive Stack>>.
Servlet API and deployed to Servlet containers. Individual chapters include <<mvc, Spring MVC>>,
<<mvc-view,View Technologies>>, <<mvc-cors,CORS Support>>, and <<websocket, WebSocket Support>>.
For reactive-stack web applications, see <<web-reactive.adoc#spring-web-reactive, Web on Reactive Stack>>.
include::web/webmvc.adoc[leveloffset=+1]

89
src/docs/asciidoc/web/integration.adoc

@ -1,16 +1,16 @@ @@ -1,16 +1,16 @@
[[web-integration]]
= Other Web Frameworks
This chapter details Spring's integration with third party web frameworks.
This chapter details Spring's integration with third-party web frameworks.
One of the core value propositions of the Spring Framework is that of enabling
_choice_. In a general sense, Spring does not force you to use or buy into any
particular architecture, technology, or methodology (although it certainly recommends
some over others). This freedom to pick and choose the architecture, technology, or
methodology that is most relevant to a developer and their development team is
arguably most evident in the web area, where Spring provides its own web framework
(<<mvc,Spring MVC>>) while, at the same time, providing integration with a number of
popular third party web frameworks.
arguably most evident in the web area, where Spring provides its own web frameworks
(<<mvc, Spring MVC>> and <<webflux, Spring WebFlux>>) while, at the same time,
supporting integration with a number of popular third-party web frameworks.
@ -19,9 +19,8 @@ popular third party web frameworks. @@ -19,9 +19,8 @@ popular third party web frameworks.
== Common Configuration
Before diving into the integration specifics of each supported web framework, let us
first take a look at the Spring configuration that is not specific to any one web
framework. (This section is equally applicable to Spring's own web framework, Spring
MVC.)
first take a look at common Spring configuration that is not specific to any one web
framework. (This section is equally applicable to Spring's own web framework variants.)
One of the concepts (for want of a better word) espoused by Spring's lightweight
application model is that of a layered architecture. Remember that in a "`classic`"
@ -90,14 +89,14 @@ key. Rather than risk getting `NullPointerExceptions` in your application, it is @@ -90,14 +89,14 @@ key. Rather than risk getting `NullPointerExceptions` in your application, it is
to use the `getRequiredWebApplicationContext()` method. This method throws an exception
when the `ApplicationContext` is missing.
Once you have a reference to the `WebApplicationContext`, you can retrieve beans by
their name or type. Most developers retrieve beans by name and then cast them to one of
their implemented interfaces.
Once you have a reference to the `WebApplicationContext`, you can retrieve beans by their
name or type. Most developers retrieve beans by name and then cast them to one of their
implemented interfaces.
Fortunately, most of the frameworks in this section have simpler ways of looking up
beans. Not only do they make it easy to get beans from a Spring container, but they also
let you use dependency injection on their controllers. Each web framework section
has more detail on its specific integration strategies.
Fortunately, most of the frameworks in this section have simpler ways of looking up beans.
Not only do they make it easy to get beans from a Spring container, but they also let you
use dependency injection on their controllers. Each web framework section has more detail
on its specific integration strategies.
@ -105,18 +104,14 @@ has more detail on its specific integration strategies. @@ -105,18 +104,14 @@ has more detail on its specific integration strategies.
[[jsf]]
== JSF
JavaServer Faces (JSF) is the JCP's standard component-based, event-driven web user
interface framework. As of Java EE 5, it is an official part of the Java EE umbrella.
JavaServer Faces (JSF) is the JCP's standard component-based, event-driven web
user interface framework. It is an official part of the Java EE umbrella but also
individually usable, e.g. through embedding Mojarra or MyFaces within Tomcat.
For a popular JSF runtime as well as for popular JSF component libraries, check out the
http://myfaces.apache.org/[Apache MyFaces project]. The MyFaces project also provides
common JSF extensions, such as http://myfaces.apache.org/orchestra/[MyFaces Orchestra]
(a Spring-based JSF extension that provides rich conversation scope support).
NOTE: Spring Web Flow 2.0 provides rich JSF support through its newly established Spring Faces
module, both for JSF-centric usage (as described in this section) and for Spring-centric
usage (using JSF views within a Spring MVC dispatcher). See the
http://projects.spring.io/spring-webflow[Spring Web Flow website] for details.
Please note that recent versions of JSF became closely tied to CDI infrastructure
in application servers, with some new JSF functionality only working in such an
environment. Spring's JSF support is not actively evolved anymore and primarily
exists for migration purposes when modernizing older JSF-based applications.
The key element in Spring's JSF integration is the JSF `ELResolver` mechanism.
@ -125,11 +120,10 @@ The key element in Spring's JSF integration is the JSF `ELResolver` mechanism. @@ -125,11 +120,10 @@ The key element in Spring's JSF integration is the JSF `ELResolver` mechanism.
[[jsf-springbeanfaceselresolver]]
=== Spring Bean Resolver
`SpringBeanFacesELResolver` is a JSF 1.2+ compliant `ELResolver` implementation,
integrating with the standard Unified EL as used by JSF 1.2 and JSP 2.1. As
`SpringBeanVariableResolver`, it delegates to Spring's "`business context`"
`WebApplicationContext` first and then to the default resolver of the underlying JSF
implementation.
`SpringBeanFacesELResolver` is a JSF compliant `ELResolver` implementation,
integrating with the standard Unified EL as used by JSF and JSP. It delegates to
Spring's "`business context`" `WebApplicationContext` first and then to the
default resolver of the underlying JSF implementation.
Configuration-wise, you can define `SpringBeanFacesELResolver` in your JSF
`faces-context.xml` file, as the following example shows:
@ -150,11 +144,11 @@ Configuration-wise, you can define `SpringBeanFacesELResolver` in your JSF @@ -150,11 +144,11 @@ Configuration-wise, you can define `SpringBeanFacesELResolver` in your JSF
[[jsf-facescontextutils]]
=== Using `FacesContextUtils`
A custom `VariableResolver` works well when mapping your properties to beans
in `faces-config.xml`, but, at times, you may need to explicitly grab a bean. The
{api-spring-framework}/web/jsf/FacesContextUtils.html[`FacesContextUtils`]
class makes this easy. It is similar to `WebApplicationContextUtils`, except that it
takes a `FacesContext` parameter rather than a `ServletContext` parameter.
A custom `ELResolver` works well when mapping your properties to beans in
`faces-config.xml`, but, at times, you may need to explicitly grab a bean.
The {api-spring-framework}/web/jsf/FacesContextUtils.html[`FacesContextUtils`]
class makes this easy. It is similar to `WebApplicationContextUtils`, except that
it takes a `FacesContext` parameter rather than a `ServletContext` parameter.
The following example shows how to use `FacesContextUtils`:
@ -173,30 +167,29 @@ The following example shows how to use `FacesContextUtils`: @@ -173,30 +167,29 @@ The following example shows how to use `FacesContextUtils`:
Invented by Craig McClanahan, http://struts.apache.org[Struts] is an open-source project
hosted by the Apache Software Foundation. At the time, it greatly simplified the
JSP/Servlet programming paradigm and won over many developers who were using proprietary
frameworks. It simplified the programming model, it was open source (and thus free, as in
beer), and it had a large community, which let the project grow and become popular
among Java web developers.
frameworks. It simplified the programming model, it was open source (and thus free as in
beer), and it had a large community, which let the project grow and become popular among
Java web developers.
Check out the Struts
As a successor to the original Struts 1.x, check out Struts 2.x and the Struts-provided
https://struts.apache.org/release/2.3.x/docs/spring-plugin.html[Spring Plugin] for the
built-in Spring integration shipped with Struts.
built-in Spring integration.
[[tapestry]]
== Tapestry 5.x
== Apache Tapestry 5.x
http://tapestry.apache.org/[Tapestry] is a ""Component oriented framework for creating dynamic, robust,
highly scalable web applications in Java.""
http://tapestry.apache.org/[Tapestry] is a ""Component oriented framework for creating
dynamic, robust, highly scalable web applications in Java.""
While Spring has its own <<mvc,powerful web layer>>, there are a number of unique
While Spring has its own <<mvc, powerful web layer>>, there are a number of unique
advantages to building an enterprise Java application by using a combination of Tapestry
for the web user interface and the Spring container for the lower layers.
For more information, see Tapestry's dedicated
https://tapestry.apache.org/integrating-with-spring-framework.html[integration module for
Spring].
https://tapestry.apache.org/integrating-with-spring-framework.html[integration module for Spring].
@ -204,8 +197,8 @@ Spring]. @@ -204,8 +197,8 @@ Spring].
[[web-integration-resources]]
== Further Resources
The following links go to further resources about the various web frameworks described in this
chapter.
The following links go to further resources about the various web frameworks described in
this chapter.
* The http://www.oracle.com/technetwork/java/javaee/javaserverfaces-139869.html[JSF] homepage
* The http://struts.apache.org/[Struts] homepage

8
src/docs/asciidoc/web/web-uris.adoc

@ -64,10 +64,10 @@ You shorter it further still with a full URI template, as the following example @@ -64,10 +64,10 @@ You shorter it further still with a full URI template, as the following example
= UriBuilder
[.small]#Spring MVC and Spring WebFlux#
<<web-uricomponents,`UriComponentsBuilder`>> implements `UriBuilder`. You can create a `UriBuilder`, in turn,
with a `UriBuilderFactory`. Together, `UriBuilderFactory` and `UriBuilder`
provide a pluggable mechanism to build URIs from URI templates, based on shared
configuration, such as a base URL, encoding preferences, and other details.
<<web-uricomponents, `UriComponentsBuilder`>> implements `UriBuilder`. You can create a
`UriBuilder`, in turn, with a `UriBuilderFactory`. Together, `UriBuilderFactory` and
`UriBuilder` provide a pluggable mechanism to build URIs from URI templates, based on
shared configuration, such as a base URL, encoding preferences, and other details.
You can configure `RestTemplate` and `WebClient` with a `UriBuilderFactory`
to customize the preparation of URIs. `DefaultUriBuilderFactory` is a default

14
src/docs/asciidoc/web/webflux-cors.adoc

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
[[webflux-cors]]
= CORS
[.small]#<<web.adoc#mvc-cors,Same as in Spring MVC>>#
[.small]#<<web.adoc#mvc-cors, Same as in Spring MVC>>#
Spring WebFlux lets you handle CORS (Cross-Origin Resource Sharing). This section
describes how to do so.
@ -10,7 +10,7 @@ describes how to do so. @@ -10,7 +10,7 @@ describes how to do so.
[[webflux-cors-intro]]
== Introduction
[.small]#<<web.adoc#mvc-cors-intro,Same as in Spring MVC>>#
[.small]#<<web.adoc#mvc-cors-intro, Same as in Spring MVC>>#
For security reasons, browsers prohibit AJAX calls to resources outside the current origin.
For example, you could have your bank account in one tab and evil.com in another. Scripts
@ -27,7 +27,7 @@ powerful workarounds based on IFRAME or JSONP. @@ -27,7 +27,7 @@ powerful workarounds based on IFRAME or JSONP.
[[webflux-cors-processing]]
== Processing
[.small]#<<web.adoc#mvc-cors-processing,Same as in Spring MVC>>#
[.small]#<<web.adoc#mvc-cors-processing, Same as in Spring MVC>>#
The CORS specification distinguishes between preflight, simple, and actual requests.
To learn how CORS works, you can read
@ -77,7 +77,7 @@ To learn more from the source or to make advanced customizations, see: @@ -77,7 +77,7 @@ To learn more from the source or to make advanced customizations, see:
[[webflux-cors-controller]]
== `@CrossOrigin`
[.small]#<<web.adoc#mvc-cors-controller,Same as in Spring MVC>>#
[.small]#<<web.adoc#mvc-cors-controller, Same as in Spring MVC>>#
The {api-spring-framework}/web/bind/annotation/CrossOrigin.html[`@CrossOrigin`]
annotation enables cross-origin requests on annotated controller methods, as the
@ -169,7 +169,7 @@ public class AccountController { @@ -169,7 +169,7 @@ public class AccountController {
[[webflux-cors-global]]
== Global Configuration
[.small]#<<web.adoc#mvc-cors-global,Same as in Spring MVC>>#
[.small]#<<web.adoc#mvc-cors-global, Same as in Spring MVC>>#
In addition to fine-grained, controller method-level configuration, you probably want to
define some global CORS configuration, too. You can set URL-based `CorsConfiguration`
@ -218,11 +218,11 @@ public class WebConfig implements WebFluxConfigurer { @@ -218,11 +218,11 @@ public class WebConfig implements WebFluxConfigurer {
[[webflux-cors-webfilter]]
== CORS `WebFilter`
[.small]#<<web.adoc#mvc-cors-filter,Same as in Spring MVC>>#
[.small]#<<web.adoc#mvc-cors-filter, Same as in Spring MVC>>#
You can apply CORS support through the built-in
{api-spring-framework}/web/cors/reactive/CorsWebFilter.html[`CorsWebFilter`], which is a
good fit with <<webflux-fn,functional endpoints>>.
good fit with <<webflux-fn, functional endpoints>>.
NOTE: If you try to use the `CorsFilter` with Spring Security, keep in mind that Spring
Security has

19
src/docs/asciidoc/web/webflux-functional.adoc

@ -64,7 +64,7 @@ public class PersonHandler { @@ -64,7 +64,7 @@ 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 <<web-reactive.adoc#webflux-httphandler,server adapters>>:
through one of the built-in <<web-reactive.adoc#webflux-httphandler, server adapters>>:
* `RouterFunctions.toHttpHandler(RouterFunction)`
* `RouterFunctions.toHttpHandler(RouterFunction, HandlerStrategies)`
@ -83,7 +83,7 @@ Both request and response provide http://www.reactive-streams.org[Reactive Strea @@ -83,7 +83,7 @@ Both request and response provide http://www.reactive-streams.org[Reactive Strea
against the body streams.
The request body is represented with a Reactor `Flux` or `Mono`.
The response body is represented with any Reactive Streams `Publisher`, including `Flux` and `Mono`.
For more on that, see <<web-reactive.adoc#webflux-reactive-libraries,Reactive Libraries>>.
For more on that, see <<web-reactive.adoc#webflux-reactive-libraries, Reactive Libraries>>.
@ -233,9 +233,9 @@ found. If it is not found, we use `switchIfEmpty(Mono<T>)` to return a 404 Not F @@ -233,9 +233,9 @@ found. If it is not found, we use `switchIfEmpty(Mono<T>)` to return a 404 Not F
[[webflux-fn-handler-validation]]
=== Validation
A functional endpoint can use Spring's <<core.adoc#validation,validation facilities>> to
A functional endpoint can use Spring's <<core.adoc#validation, validation facilities>> to
apply validation to the request body. For example, given a custom Spring
<<core.adoc#validation,Validator>> implementation for a `Person`:
<<core.adoc#validation, Validator>> implementation for a `Person`:
====
[source,java,indent=0]
@ -268,7 +268,7 @@ public class PersonHandler { @@ -268,7 +268,7 @@ public class PersonHandler {
Handlers can also use the standard bean validation API (JSR-303) by creating and injecting
a global `Validator` instance based on `LocalValidatorFactoryBean`.
See <<core.adoc#validation-beanvalidation,Spring Validation>>.
See <<core.adoc#validation-beanvalidation, Spring Validation>>.
@ -424,10 +424,10 @@ function to an `HttpHandler` by using one of the following: @@ -424,10 +424,10 @@ function to an `HttpHandler` by using one of the following:
* `RouterFunctions.toHttpHandler(RouterFunction, HandlerStrategies)`
You can then use the returned `HttpHandler` with a number of server adapters by following
<<web-reactive.adoc#webflux-httphandler,HttpHandler>> for server-specific instructions.
<<web-reactive.adoc#webflux-httphandler, HttpHandler>> for server-specific instructions.
A more typical option, also used by Spring Boot, is to run with a
<<web-reactive.adoc#webflux-dispatcher-handler,`DispatcherHandler`>>-based setup through the
<<web-reactive.adoc#webflux-dispatcher-handler, `DispatcherHandler`>>-based setup through the
<<web-reactive.adoc#webflux-config>>, which uses Spring configuration to declare the
components required to process requests. The WebFlux Java configuration declares the following
infrastructure components to support functional endpoints:
@ -446,7 +446,7 @@ any are declared. It is also how functional endpoints are enabled by the Spring @@ -446,7 +446,7 @@ any are declared. It is also how functional endpoints are enabled by the Spring
starter.
The following example shows a WebFlux Java configuration (see
<<web-reactive.adoc#webflux-dispatcher-handler,DispatcherHandler>> for how to run it):
<<web-reactive.adoc#webflux-dispatcher-handler, DispatcherHandler>> for how to run it):
[source,java,indent=0]
[subs="verbatim,quotes"]
@ -555,4 +555,5 @@ We allow only the handler function to be executed when access is allowed. @@ -555,4 +555,5 @@ We allow only the handler function to be executed when access is allowed.
Besides using the `filter` method on the router function builder, it is possible to apply a
filter to an existing router function via `RouterFunction.filter(HandlerFilterFunction)`.
NOTE: CORS support for functional endpoints is provided through a dedicated <<webflux-cors-webfilter,`CorsWebFilter`>>.
NOTE: CORS support for functional endpoints is provided through a dedicated
<<webflux-cors-webfilter, `CorsWebFilter`>>.

34
src/docs/asciidoc/web/webflux-view.adoc

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
[[webflux-view]]
= View Technologies
[.small]#<<web.adoc#mvc-view,Same as in Spring MVC>>#
[.small]#<<web.adoc#mvc-view, Same as in Spring MVC>>#
The use of view technologies in Spring WebFlux is pluggable. Whether you decide to
use Thymeleaf, FreeMarker, or some other view technology is primarily a matter of a
@ -12,7 +12,7 @@ WebFlux. We assume you are already familiar with <<webflux-viewresolution>>. @@ -12,7 +12,7 @@ WebFlux. We assume you are already familiar with <<webflux-viewresolution>>.
[[webflux-view-thymeleaf]]
== Thymeleaf
[.small]#<<web.adoc#mvc-view-thymeleaf,Same as in Spring MVC>>#
[.small]#<<web.adoc#mvc-view-thymeleaf, Same as in Spring MVC>>#
Thymeleaf is a modern server-side Java template engine that emphasizes natural HTML
templates that can be previewed in a browser by double-clicking, which is very
@ -33,7 +33,7 @@ http://forum.thymeleaf.org/Thymeleaf-3-0-8-JUST-PUBLISHED-td4030687.html[announc @@ -33,7 +33,7 @@ http://forum.thymeleaf.org/Thymeleaf-3-0-8-JUST-PUBLISHED-td4030687.html[announc
[[webflux-view-freemarker]]
== FreeMarker
[.small]#<<web.adoc#mvc-view-freemarker,Same as in Spring MVC>>#
[.small]#<<web.adoc#mvc-view-freemarker, Same as in Spring MVC>>#
http://www.freemarker.org[Apache FreeMarker] is a template engine for generating any
kind of text output from HTML to email and others. The Spring Framework has a built-in
@ -43,7 +43,7 @@ integration for using Spring WebFlux with FreeMarker templates. @@ -43,7 +43,7 @@ integration for using Spring WebFlux with FreeMarker templates.
[[webflux-view-freemarker-contextconfig]]
=== View Configuration
[.small]#<<web.adoc#mvc-view-freemarker-contextconfig,Same as in Spring MVC>>#
[.small]#<<web.adoc#mvc-view-freemarker-contextconfig, Same as in Spring MVC>>#
The following example shows how to configure FreeMarker as a view technology:
@ -79,7 +79,7 @@ shown in the preceding example. Given the preceding configuration, if your contr @@ -79,7 +79,7 @@ shown in the preceding example. Given the preceding configuration, if your contr
[[webflux-views-freemarker]]
=== FreeMarker Configuration
[.small]#<<web.adoc#mvc-views-freemarker,Same as in Spring MVC>>#
[.small]#<<web.adoc#mvc-views-freemarker, Same as in Spring MVC>>#
You can pass FreeMarker 'Settings' and 'SharedVariables' directly to the FreeMarker
`Configuration` object (managed by Spring) by setting the appropriate bean properties on
@ -117,7 +117,7 @@ the `Configuration` object. @@ -117,7 +117,7 @@ the `Configuration` object.
[[webflux-view-script]]
== Script Views
[.small]#<<web.adoc#mvc-view-script,Same as in Spring MVC>>#
[.small]#<<web.adoc#mvc-view-script, Same as in Spring MVC>>#
The Spring Framework has a built-in integration for using Spring WebFlux with any
templating library that can run on top of the
@ -143,7 +143,7 @@ TIP: The basic rule for integrating any other script engine is that it must impl @@ -143,7 +143,7 @@ TIP: The basic rule for integrating any other script engine is that it must impl
[[webflux-view-script-dependencies]]
=== Requirements
[.small]#<<web.adoc#mvc-view-script-dependencies,Same as in Spring MVC>>#
[.small]#<<web.adoc#mvc-view-script-dependencies, Same as in Spring MVC>>#
You need to have the script engine on your classpath, the details of which vary by script engine:
@ -163,7 +163,7 @@ through http://www.webjars.org/[WebJars]. @@ -163,7 +163,7 @@ through http://www.webjars.org/[WebJars].
[[webflux-view-script-integrate]]
=== Script Templates
[.small]#<<web.adoc#mvc-view-script-integrate,Same as in Spring MVC>>#
[.small]#<<web.adoc#mvc-view-script-integrate, Same as in Spring MVC>>#
You can declare a `ScriptTemplateConfigurer` bean to specify the script engine to use,
the script files to load, what function to call to render templates, and so on.
@ -274,20 +274,20 @@ for more configuration examples. @@ -274,20 +274,20 @@ for more configuration examples.
[[webflux-view-httpmessagewriter]]
== JSON and XML
[.small]#<<web.adoc#mvc-view-jackson,Same as in Spring MVC>>#
[.small]#<<web.adoc#mvc-view-jackson, Same as in Spring MVC>>#
For <<webflux-multiple-representations>> purposes, it is useful to be able to alternate
between rendering a model with an HTML template or as other formats (such as JSON or XML),
depending on the content type requested by the client. To support doing so, Spring WebFlux
provides the `HttpMessageWriterView`, which you can use to plug in any of the available
<<webflux-codecs>> from `spring-web`, such as `Jackson2JsonEncoder`,
`Jackson2SmileEncoder`, or `Jaxb2XmlEncoder`.
<<webflux-codecs>> from `spring-web`, such as `Jackson2JsonEncoder`, `Jackson2SmileEncoder`,
or `Jaxb2XmlEncoder`.
Unlike other view technologies, `HttpMessageWriterView` does not require a `ViewResolver`
but is instead <<webflux-config-view-resolvers,configured>> as a default view. You can
configure one or more such default views, wrapping different `HttpMessageWriter` instances or
`Encoder` instances. The one that matches the requested content type is used at runtime.
but is instead <<webflux-config-view-resolvers, configured>> as a default view. You can
configure one or more such default views, wrapping different `HttpMessageWriter` instances
or `Encoder` instances. The one that matches the requested content type is used at runtime.
In most cases, a model contains multiple attributes. To determine which one
to serialize, you can configure `HttpMessageWriterView` with the name of the model
attribute to use for rendering. If the model contains only one attribute, that one is used.
In most cases, a model contains multiple attributes. To determine which one to serialize,
you can configure `HttpMessageWriterView` with the name of the model attribute to use for
rendering. If the model contains only one attribute, that one is used.

4
src/docs/asciidoc/web/webflux-webclient.adoc

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
Spring WebFlux includes a reactive, non-blocking `WebClient` for HTTP requests. The client
has a functional, fluent API with reactive types for declarative composition, see
<<web-reactive.adoc#webflux-reactive-libraries>>. WebFlux client and server rely on the
same non-blocking <<web-reactive.adoc#webflux-codecs,codecs>> to encode and decode request
same non-blocking <<web-reactive.adoc#webflux-codecs, codecs>> to encode and decode request
and response content.
Internally `WebClient` delegates to an HTTP client library. By default, it uses
@ -36,7 +36,7 @@ You can also use `WebClient.builder()` with further options: @@ -36,7 +36,7 @@ You can also use `WebClient.builder()` with further options:
* `exchangeStrategies`: HTTP message reader/writer customizations.
* `clientConnector`: HTTP client library settings.
The following example configures <<web-reactive.adoc#webflux-codecs,HTTP codecs>>:
The following example configures <<web-reactive.adoc#webflux-codecs, HTTP codecs>>:
[source,java,intent=0]
[subs="verbatim,quotes"]

16
src/docs/asciidoc/web/webflux-websocket.adoc

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
[[webflux-websocket]]
= WebSockets
[.small]#<<web.adoc#websocket,Same as in the Servlet stack>>#
[.small]#<<web.adoc#websocket, Same as in the Servlet stack>>#
This part of the reference documentation covers support for reactive-stack WebSocket
messaging.
@ -12,7 +12,7 @@ include::websocket-intro.adoc[leveloffset=+1] @@ -12,7 +12,7 @@ include::websocket-intro.adoc[leveloffset=+1]
[[webflux-websocket-server]]
== WebSocket API
[.small]#<<web.adoc#websocket-server,Same as in the Servlet stack>>#
[.small]#<<web.adoc#websocket-server, Same as in the Servlet stack>>#
The Spring Framework provides a WebSocket API that you can use to write client- and
server-side applications that handle WebSocket messages.
@ -21,7 +21,7 @@ server-side applications that handle WebSocket messages. @@ -21,7 +21,7 @@ server-side applications that handle WebSocket messages.
[[webflux-websocket-server-handler]]
=== Server
[.small]#<<web.adoc#websocket-server-handler,Same as in the Servlet stack>>#
[.small]#<<web.adoc#websocket-server-handler, Same as in the Servlet stack>>#
To create a WebSocket server, you can first create a `WebSocketHandler`.
The following example shows how to do so:
@ -133,7 +133,7 @@ class ExampleHandler implements WebSocketHandler { @@ -133,7 +133,7 @@ class ExampleHandler implements WebSocketHandler {
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
released before you have had a chance to read the data. For more background, see
<<core.adoc#databuffers,Data Buffers and Codecs>>.
<<core.adoc#databuffers, Data Buffers and Codecs>>.
The following implementation combines the inbound and outbound streams:
@ -201,7 +201,7 @@ class ExampleHandler implements WebSocketHandler { @@ -201,7 +201,7 @@ class ExampleHandler implements WebSocketHandler {
`DataBuffer` is the representation for a byte buffer in WebFlux. The Spring Core part of
the reference has more on that in the section on
<<core#databuffers,Data Buffers and Codecs>>. The key point to understand is that on some
<<core#databuffers, Data Buffers and Codecs>>. The key point to understand is that on some
servers like Netty, byte buffers are pooled and reference counted, and must be released
when consumed to avoid memory leaks.
@ -214,7 +214,7 @@ subsequently use `DataBufferUtils.release(dataBuffer)` when the buffers are cons @@ -214,7 +214,7 @@ subsequently use `DataBufferUtils.release(dataBuffer)` when the buffers are cons
[[webflux-websocket-server-handshake]]
=== Handshake
[.small]#<<web.adoc#websocket-server-handshake,Same as in the Servlet stack>>#
[.small]#<<web.adoc#websocket-server-handshake, Same as in the Servlet stack>>#
`WebSocketHandlerAdapter` delegates to a `WebSocketService`. By default, that is an instance
of `HandshakeWebSocketService`, which performs basic checks on the WebSocket request and
@ -229,7 +229,7 @@ into the attributes of the `WebSocketSession`. @@ -229,7 +229,7 @@ into the attributes of the `WebSocketSession`.
[[webflux-websocket-server-config]]
=== Server Configation
[.small]#<<web.adoc#websocket-server-runtime-configuration,Same as in the Servlet stack>>#
[.small]#<<web.adoc#websocket-server-runtime-configuration, Same as in the Servlet stack>>#
The `RequestUpgradeStrategy` for each server exposes WebSocket-related configuration
options available for the underlying WebSocket engine. The following example sets
@ -262,7 +262,7 @@ only Tomcat and Jetty expose such options. @@ -262,7 +262,7 @@ only Tomcat and Jetty expose such options.
[[webflux-websocket-server-cors]]
=== CORS
[.small]#<<web.adoc#websocket-server-allowed-origins,Same as in the Servlet stack>>#
[.small]#<<web.adoc#websocket-server-allowed-origins, Same as in the Servlet stack>>#
The easiest way to configure CORS and restrict access to a WebSocket endpoint is to
have your `WebSocketHandler` implement `CorsConfigurationSource` and return a

311
src/docs/asciidoc/web/webflux.adoc

File diff suppressed because it is too large Load Diff

6
src/docs/asciidoc/web/webmvc-client.adoc

@ -15,12 +15,12 @@ libraries. @@ -15,12 +15,12 @@ libraries.
NOTE: As of 5.0, the non-blocking, reactive `WebClient` offers a modern alternative to the
`RestTemplate`, with efficient support for both
<<web-reactive.adoc#webflux-client-synchronous,synchronous and asynchronous>>, as well as
<<web-reactive.adoc#webflux-client-synchronous, synchronous and asynchronous>>, as well as
streaming scenarios. The `RestTemplate` will be deprecated in a future version and will
not have major new features added going forward.
See <<integration.adoc#rest-client-access,REST Endpoints>> for details.
See <<integration.adoc#rest-client-access, REST Endpoints>> for details.
@ -41,4 +41,4 @@ In contrast to `RestTemplate`, `WebClient` supports the following: @@ -41,4 +41,4 @@ In contrast to `RestTemplate`, `WebClient` supports the following:
* Synchronous and asynchronous interactions.
* Streaming up to or streaming down from a server.
See <<web-reactive.adoc#webflux-client,WebClient>> for more details.
See <<web-reactive.adoc#webflux-client, WebClient>> for more details.

18
src/docs/asciidoc/web/webmvc-cors.adoc

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
[[mvc-cors]]
= CORS
[.small]#<<web-reactive.adoc#webflux-cors,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-cors, Same as in Spring WebFlux>>#
Spring MVC lets you handle CORS (Cross-Origin Resource Sharing). This section
describes how to do so.
@ -10,7 +10,7 @@ describes how to do so. @@ -10,7 +10,7 @@ describes how to do so.
[[mvc-cors-intro]]
== Introduction
[.small]#<<web-reactive.adoc#webflux-cors-intro,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-cors-intro, Same as in Spring WebFlux>>#
For security reasons, browsers prohibit AJAX calls to resources outside the current origin.
For example, you could have your bank account in one tab and evil.com in another. Scripts
@ -27,7 +27,7 @@ powerful workarounds based on IFRAME or JSONP. @@ -27,7 +27,7 @@ powerful workarounds based on IFRAME or JSONP.
[[mvc-cors-processing]]
== Processing
[.small]#<<web-reactive.adoc#webflux-cors-processing,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-cors-processing, Same as in Spring WebFlux>>#
The CORS specification distinguishes between preflight, simple, and actual requests.
To learn how CORS works, you can read
@ -77,7 +77,7 @@ To learn more from the source or make advanced customizations, check the code be @@ -77,7 +77,7 @@ To learn more from the source or make advanced customizations, check the code be
[[mvc-cors-controller]]
== `@CrossOrigin`
[.small]#<<web-reactive.adoc#webflux-cors-controller,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-cors-controller, Same as in Spring WebFlux>>#
The {api-spring-framework}/web/bind/annotation/CrossOrigin.html[`@CrossOrigin`]
annotation enables cross-origin requests on annotated controller methods,
@ -167,7 +167,7 @@ public class AccountController { @@ -167,7 +167,7 @@ public class AccountController {
[[mvc-cors-global]]
== Global Configuration
[.small]#<<web-reactive.adoc#webflux-cors-global,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-cors-global, Same as in Spring WebFlux>>#
In addition to fine-grained, controller method level configuration, you probably want to
define some global CORS configuration, too. You can set URL-based `CorsConfiguration`
@ -191,7 +191,7 @@ should only be used where appropriate. @@ -191,7 +191,7 @@ should only be used where appropriate.
[[mvc-cors-global-java]]
=== Java Configuration
[.small]#<<web-reactive.adoc#webflux-cors-global,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-cors-global, Same as in Spring WebFlux>>#
To enable CORS in the MVC Java config, you can use the `CorsRegistry` callback,
as the following example shows:
@ -249,13 +249,13 @@ as the following example shows: @@ -249,13 +249,13 @@ as the following example shows:
[[mvc-cors-filter]]
== CORS Filter
[.small]#<<web-reactive.adoc#webflux-cors-webfilter,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-cors-webfilter, Same as in Spring WebFlux>>#
You can apply CORS support through the built-in
{api-spring-framework}/web/filter/CorsFilter.html[`CorsFilter`].
NOTE: If you try to use the `CorsFilter` with Spring Security, keep in mind that Spring
Security has
NOTE: If you try to use the `CorsFilter` with Spring Security, keep in mind that
Spring Security has
https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#cors[built-in support]
for CORS.

28
src/docs/asciidoc/web/webmvc-test.adoc

@ -1,26 +1,26 @@ @@ -1,26 +1,26 @@
[[testing]]
= Testing
[.small]#<<web-reactive.adoc#webflux-test,Same in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-test, Same in Spring WebFlux>>#
This section summarizes the options available in `spring-test` for Spring MVC applications.
* Servlet API Mocks: Mock implementations of Servlet API contracts for unit testing controllers, filters, and
other web components. See <<testing.adoc#mock-objects-servlet,Servlet API>> mock objects
for more details.
* Servlet API Mocks: Mock implementations of Servlet API contracts for unit testing controllers,
filters, and other web components. See <<testing.adoc#mock-objects-servlet, Servlet API>>
mock objects for more details.
* TestContext Framework: Support for loading Spring configuration in JUnit and TestNG tests, including efficient
caching of the loaded configuration across test methods and support for loading a
`WebApplicationContext` with a `MockServletContext`.
* TestContext Framework: Support for loading Spring configuration in JUnit and TestNG tests,
including efficient caching of the loaded configuration across test methods and support for
loading a `WebApplicationContext` with a `MockServletContext`.
See <<testing.adoc#testcontext-framework,TestContext Framework>> for more details.
* Spring MVC Test: A framework, also known as `MockMvc`, for testing annotated controllers through the
`DispatcherServlet` (that is, supporting annotations), complete with the Spring MVC
infrastructure but without an HTTP server. See
<<testing.adoc#spring-mvc-test-framework,Spring MVC Test>> for more details.
* Spring MVC Test: A framework, also known as `MockMvc`, for testing annotated controllers
through the `DispatcherServlet` (that is, supporting annotations), complete with the
Spring MVC infrastructure but without an HTTP server.
See <<testing.adoc#spring-mvc-test-framework, Spring MVC Test>> for more details.
* Client-side REST: `spring-test` provides a `MockRestServiceServer` that you can use as a mock server for
testing client-side code that internally uses the `RestTemplate`.
See <<testing.adoc#spring-mvc-test-client,Client REST Tests>> for more details.
* Client-side REST: `spring-test` provides a `MockRestServiceServer` that you can use as
a mock server for testing client-side code that internally uses the `RestTemplate`.
See <<testing.adoc#spring-mvc-test-client, Client REST Tests>> for more details.
* `WebTestClient`: Built for testing WebFlux applications, but it can also be used for
end-to-end integration testing, to any server, over an HTTP connection. It is a

44
src/docs/asciidoc/web/webmvc-view.adoc

@ -1,18 +1,18 @@ @@ -1,18 +1,18 @@
[[mvc-view]]
= View Technologies
[.small]#<<web-reactive.adoc#webflux-view,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-view, Same as in Spring WebFlux>>#
The use of view technologies in Spring MVC is pluggable, whether you decide to
use Thymeleaf, Groovy Markup Templates, JSPs, or other technologies, is primarily a matter of a
configuration change. This chapter covers view technologies integrated with Spring MVC.
We assume you are already familiar with <<mvc-viewresolver>>.
The use of view technologies in Spring MVC is pluggable, whether you decide to use
Thymeleaf, Groovy Markup Templates, JSPs, or other technologies, is primarily a matter
of a configuration change. This chapter covers view technologies integrated with
Spring MVC. We assume you are already familiar with <<mvc-viewresolver>>.
[[mvc-view-thymeleaf]]
== Thymeleaf
[.small]#<<web-reactive.adoc#webflux-view-thymeleaf,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-view-thymeleaf, Same as in Spring WebFlux>>#
Thymeleaf is a modern server-side Java template engine that emphasizes natural HTML
templates that can be previewed in a browser by double-clicking, which is very helpful
@ -32,7 +32,7 @@ See http://www.thymeleaf.org/documentation.html[Thymeleaf+Spring] for more detai @@ -32,7 +32,7 @@ See http://www.thymeleaf.org/documentation.html[Thymeleaf+Spring] for more detai
[[mvc-view-freemarker]]
== FreeMarker
[.small]#<<web-reactive.adoc#webflux-view-freemarker,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-view-freemarker, Same as in Spring WebFlux>>#
http://www.freemarker.org[Apache FreeMarker] is a template engine for generating any
kind of text output from HTML to email and others. The Spring Framework has a built-in
@ -42,7 +42,7 @@ integration for using Spring MVC with FreeMarker templates. @@ -42,7 +42,7 @@ integration for using Spring MVC with FreeMarker templates.
[[mvc-view-freemarker-contextconfig]]
=== View Configuration
[.small]#<<web-reactive.adoc#webflux-view-freemarker-contextconfig,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-view-freemarker-contextconfig, Same as in Spring WebFlux>>#
The following example shows how to configure FreeMarker as a view technology:
@ -105,7 +105,7 @@ of `welcome`, the resolver looks for the `/WEB-INF/freemarker/welcome.ftl` templ @@ -105,7 +105,7 @@ of `welcome`, the resolver looks for the `/WEB-INF/freemarker/welcome.ftl` templ
[[mvc-views-freemarker]]
=== FreeMarker Configuration
[.small]#<<web-reactive.adoc#webflux-views-freemarker,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-views-freemarker, Same as in Spring WebFlux>>#
You can pass FreeMarker 'Settings' and 'SharedVariables' directly to the FreeMarker
`Configuration` object (which is managed by Spring) by setting the appropriate bean properties on
@ -536,7 +536,7 @@ syntax. The following example shows a sample template for an HTML page: @@ -536,7 +536,7 @@ syntax. The following example shows a sample template for an HTML page:
[[mvc-view-script]]
== Script Views
[.small]#<<web-reactive.adoc#webflux-view-script,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-view-script, Same as in Spring WebFlux>>#
The Spring Framework has a built-in integration for using Spring MVC with any
templating library that can run on top of the
@ -562,7 +562,7 @@ TIP: The basic rule for integrating any other script engine is that it must impl @@ -562,7 +562,7 @@ TIP: The basic rule for integrating any other script engine is that it must impl
[[mvc-view-script-dependencies]]
=== Requirements
[.small]#<<web-reactive.adoc#webflux-view-script-dependencies,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-view-script-dependencies, Same as in Spring WebFlux>>#
You need to have the script engine on your classpath, the details of which vary by script engine:
@ -582,7 +582,7 @@ through http://www.webjars.org/[WebJars]. @@ -582,7 +582,7 @@ through http://www.webjars.org/[WebJars].
[[mvc-view-script-integrate]]
=== Script Templates
[.small]#<<web-reactive.adoc#webflux-script-integrate,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-script-integrate, Same as in Spring WebFlux>>#
You can declare a `ScriptTemplateConfigurer` bean to specify the script engine to use,
the script files to load, what function to call to render templates, and so on.
@ -1126,13 +1126,13 @@ but with different values, as the following example shows: @@ -1126,13 +1126,13 @@ but with different values, as the following example shows:
This tag renders multiple HTML `input` elements with the `type` set to `radio`.
As with the <<mvc-view-jsp-formtaglib-checkboxestag,`checkboxes` tag>>, you might want to pass in the available options as
a runtime variable. For this usage, you can use the `radiobuttons` tag. You pass in an
`Array`, a `List`, or a `Map` that contains the available options in the `items` property.
If you use a `Map`, the map entry key is used as the value and the map
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:
As with the <<mvc-view-jsp-formtaglib-checkboxestag, `checkboxes` tag>>, you might want to
pass in the available options as a runtime variable. For this usage, you can use the
`radiobuttons` tag. You pass in an `Array`, a `List`, or a `Map` that contains the
available options in the `items` property. If you use a `Map`, the map entry key is
used as the value and the map 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"]
@ -1892,7 +1892,7 @@ an external definition (by name) or as a `View` instance from the handler method @@ -1892,7 +1892,7 @@ an external definition (by name) or as a `View` instance from the handler method
[[mvc-view-jackson]]
== Jackson
[.small]#<<web-reactive.adoc#webflux-view-httpmessagewriter,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-view-httpmessagewriter, Same as in Spring WebFlux>>#
Spring offers support for the Jackson JSON library.
@ -1900,7 +1900,7 @@ Spring offers support for the Jackson JSON library. @@ -1900,7 +1900,7 @@ Spring offers support for the Jackson JSON library.
[[mvc-view-json-mapping]]
=== Jackson-based JSON MVC Views
[.small]#<<web-reactive.adoc#webflux-view-httpmessagewriter,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-view-httpmessagewriter, Same as in Spring WebFlux>>#
The `MappingJackson2JsonView` uses the Jackson library's `ObjectMapper` to render the response
content as JSON. By default, the entire contents of the model map (with the exception of
@ -1919,7 +1919,7 @@ serializers and deserializers for specific types. @@ -1919,7 +1919,7 @@ serializers and deserializers for specific types.
[[mvc-view-xml-mapping]]
=== Jackson-based XML Views
[.small]#<<web-reactive.adoc#webflux-view-httpmessagewriter,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-view-httpmessagewriter, Same as in Spring WebFlux>>#
`MappingJackson2XmlView` uses the
https://github.com/FasterXML/jackson-dataformat-xml[Jackson XML extension's] `XmlMapper`

338
src/docs/asciidoc/web/webmvc.adoc

File diff suppressed because it is too large Load Diff

75
src/docs/asciidoc/web/websocket.adoc

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
[[websocket]]
= WebSockets
:doc-spring-security: {doc-root}/spring-security/site/docs/current/reference
[.small]#<<web-reactive.adoc#webflux-websocket,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-websocket, Same as in Spring WebFlux>>#
This part of the reference documentation covers support for Servlet stack, WebSocket
messaging that includes raw WebSocket interactions, WebSocket emulation through SockJS, and
@ -14,7 +14,7 @@ include::websocket-intro.adoc[leveloffset=+1] @@ -14,7 +14,7 @@ include::websocket-intro.adoc[leveloffset=+1]
[[websocket-server]]
== WebSocket API
[.small]#<<web-reactive.adoc#webflux-websocket-server,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-websocket-server, Same as in Spring WebFlux>>#
The Spring Framework provides a WebSocket API that you can use to write client- and
server-side applications that handle WebSocket messages.
@ -23,7 +23,7 @@ server-side applications that handle WebSocket messages. @@ -23,7 +23,7 @@ server-side applications that handle WebSocket messages.
[[websocket-server-handler]]
=== `WebSocketHandler`
[.small]#<<web-reactive.adoc#webflux-websocket-server-handler,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-websocket-server-handler, Same as in Spring WebFlux>>#
Creating a WebSocket server is as simple as implementing `WebSocketHandler` or, more
likely, extending either `TextWebSocketHandler` or `BinaryWebSocketHandler`. The following
@ -96,10 +96,10 @@ The following example shows the XML configuration equivalent of the preceding ex @@ -96,10 +96,10 @@ The following example shows the XML configuration equivalent of the preceding ex
</beans>
----
The preceding example is for use in Spring MVC applications and should be included in the
configuration of a <<mvc-servlet,`DispatcherServlet`>>. However, Spring's WebSocket
support does not depend on Spring MVC. It is relatively simple to integrate a `WebSocketHandler`
into other HTTP-serving environments with the help of
The preceding example is for use in Spring MVC applications and should be included
in the configuration of a <<mvc-servlet, `DispatcherServlet`>>. However, Spring's
WebSocket support does not depend on Spring MVC. It is relatively simple to
integrate a `WebSocketHandler` into other HTTP-serving environments with the help of
{api-spring-framework}/web/socket/server/support/WebSocketHttpRequestHandler.html[`WebSocketHttpRequestHandler`].
When using the `WebSocketHandler` API directly vs indirectly, e.g. through the
@ -112,7 +112,7 @@ sending. One option is to wrap the `WebSocketSession` with @@ -112,7 +112,7 @@ sending. One option is to wrap the `WebSocketSession` with
[[websocket-server-handshake]]
=== WebSocket Handshake
[.small]#<<web-reactive.adoc#webflux-websocket-server-handshake,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-websocket-server-handshake, Same as in Spring WebFlux>>#
The easiest way to customize the initial HTTP WebSocket handshake request is through
a `HandshakeInterceptor`, which exposes methods for "`before`" and "`after`" the handshake.
@ -258,7 +258,7 @@ Java initialization API. The following example shows how to do so: @@ -258,7 +258,7 @@ Java initialization API. The following example shows how to do so:
[[websocket-server-runtime-configuration]]
=== Server Configuration
[.small]#<<web-reactive.adoc#webflux-websocket-server-config,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-websocket-server-config, Same as in Spring WebFlux>>#
Each underlying WebSocket engine exposes configuration properties that control
runtime characteristics, such as the size of message buffer sizes, idle timeout,
@ -385,7 +385,7 @@ The following example shows the XML configuration equivalent of the preceding ex @@ -385,7 +385,7 @@ The following example shows the XML configuration equivalent of the preceding ex
[[websocket-server-allowed-origins]]
=== Allowed Origins
[.small]#<<web-reactive.adoc#webflux-websocket-server-cors,Same as in Spring WebFlux>>#
[.small]#<<web-reactive.adoc#webflux-websocket-server-cors, Same as in Spring WebFlux>>#
As of Spring Framework 4.1.5, the default behavior for WebSocket and SockJS is to accept
only same-origin requests. It is also possible to allow all or a specified list of origins.
@ -589,7 +589,7 @@ The following example shows the XML configuration equivalent of the preceding ex @@ -589,7 +589,7 @@ 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 <<mvc-servlet,`DispatcherServlet`>>. However, Spring's WebSocket
configuration of a <<mvc-servlet, `DispatcherServlet`>>. However, Spring's WebSocket
and SockJS support does not depend on Spring MVC. It is relatively simple to
integrate into other HTTP serving environments with the help of
{api-spring-framework}/web/socket/sockjs/support/SockJsHttpRequestHandler.html[`SockJsHttpRequestHandler`].
@ -960,7 +960,7 @@ made about HTTP versus raw TCP and how it lets Spring MVC and other web framewor @@ -960,7 +960,7 @@ made about HTTP versus raw TCP and how it lets Spring MVC and other web framewor
provide rich functionality. The following is a list of benefits:
* No need to invent a custom messaging protocol and message format.
* STOMP clients, including a <<websocket-stomp-client,Java client>>
* STOMP clients, including a <<websocket-stomp-client, Java client>>
in the Spring Framework, are available.
* You can (optionally) use message brokers (such as RabbitMQ, ActiveMQ, and others) to
manage subscriptions and broadcast messages.
@ -1070,10 +1070,10 @@ Alternatively, if you connect through WebSocket (without SockJS), you can use th @@ -1070,10 +1070,10 @@ Alternatively, if you connect through WebSocket (without SockJS), you can use th
}
----
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
<<websocket-stomp-handle-broker-relay-configure>> and
<<websocket-stomp-authentication>> for more information on authentication.
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 <<websocket-stomp-handle-broker-relay-configure>>
and <<websocket-stomp-authentication>> for more information on authentication.
For more example code see:
@ -1197,7 +1197,6 @@ We can trace the flow through a simple example. Consider the following example, @@ -1197,7 +1197,6 @@ We can trace the flow through a simple example. Consider the following example,
registry.setApplicationDestinationPrefixes("/app");
registry.enableSimpleBroker("/topic");
}
}
@Controller
@ -1207,9 +1206,7 @@ We can trace the flow through a simple example. Consider the following example, @@ -1207,9 +1206,7 @@ We can trace the flow through a simple example. Consider the following example,
public String handle(String greeting) {
return "[" + getTimestamp() + ": " + greeting;
}
}
----
The preceding example supports the following flow:
@ -1257,9 +1254,10 @@ level, `@MessageMapping` is used to express shared mappings across all methods i @@ -1257,9 +1254,10 @@ level, `@MessageMapping` is used to express shared mappings across all methods i
controller.
By default, the mapping values are Ant-style path patterns (for example `/thing*`, `/thing/**`),
including support for template variables (for example, `/thing/{id}`). The values can be referenced through
`@DestinationVariable` method arguments. Applications can also switch to a dot-separated
destination convention for mappings, as explained in <<websocket-stomp-destination-separator>>.
including support for template variables (for example, `/thing/{id}`). The values can be
referenced through `@DestinationVariable` method arguments. Applications can also switch to
a dot-separated destination convention for mappings, as explained in
<<websocket-stomp-destination-separator>>.
===== Supported Method Arguments
@ -1337,7 +1335,7 @@ See <<websocket-stomp-handle-send>>. @@ -1337,7 +1335,7 @@ See <<websocket-stomp-handle-send>>.
`@SubscribeMapping` is similar to `@MessageMapping` but narrows the mapping to
subscription messages only. It supports the same
<<websocket-stomp-message-mapping,method arguments>> as `@MessageMapping`. However
<<websocket-stomp-message-mapping, method arguments>> as `@MessageMapping`. However
for the return value, by default, a message is sent directly to the client (through
`clientOutboundChannel`, in response to the subscription) and not to the broker (through
`brokerChannel`, as a broadcast to matching subscriptions). Adding `@SendTo` or
@ -1348,8 +1346,8 @@ application controllers are mapped to `/app`. In this setup, the broker stores a @@ -1348,8 +1346,8 @@ application controllers are mapped to `/app`. In this setup, the broker stores a
subscriptions to `/topic` and `/queue` that are intended for repeated broadcasts, and
there is no need for the application to get involved. A client could also also subscribe to
some `/app` destination, and a controller could return a value in response to that
subscription without involving the broker
without storing or using the subscription again (effectively a one-time request-reply exchange). One use case for this is populating a UI
subscription without involving the broker without storing or using the subscription again
(effectively a one-time request-reply exchange). One use case for this is populating a UI
with initial data on startup.
When is this not useful? Do not try to map broker and controllers to the same destination
@ -1379,7 +1377,7 @@ receipt if the server supports it (simple broker does not). For example, with th @@ -1379,7 +1377,7 @@ receipt if the server supports it (simple broker does not). For example, with th
});
----
A server side option is <<websocket-stomp-interceptors,to register>> an
A server side option is <<websocket-stomp-interceptors, to register>> an
`ExecutorChannelInterceptor` on the `brokerChannel` and implement the `afterMessageHandled`
method that is invoked after messages, including subscriptions, have been handled.
@ -1408,13 +1406,15 @@ The following example declares an exception through a method argument: @@ -1408,13 +1406,15 @@ 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 <<websocket-stomp-message-mapping,`@MessageMapping`>> methods.
`@MessageExceptionHandler` methods support flexible method signatures and support
the same method argument types and return values as
<<websocket-stomp-message-mapping, `@MessageMapping`>> methods.
Typically, `@MessageExceptionHandler` methods apply within the `@Controller` class (or
class hierarchy) in which they are declared. If you want such methods to apply more globally
(across controllers), you can declare them in a class marked with `@ControllerAdvice`.
This is comparable to <<web.adoc#mvc-ann-controller-advice,the similar support>> that is available in Spring MVC.
Typically, `@MessageExceptionHandler` methods apply within the `@Controller` class
(or class hierarchy) in which they are declared. If you want such methods to apply
more globally (across controllers), you can declare them in a class marked with
`@ControllerAdvice`. This is comparable to the
<<web.adoc#mvc-ann-controller-advice, similar support>> available in Spring MVC.
@ -1563,10 +1563,10 @@ The following example shows the XML configuration equivalent of the preceding ex @@ -1563,10 +1563,10 @@ 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`]
that handles messages by forwarding them to an external message broker.
To do so, it establishes TCP connections to the broker, forwards all
messages to it, and then forwards all messages received
from the broker to clients through their WebSocket sessions. Essentially,
it acts as a "`relay`" that forwards messages in both directions.
To do so, it establishes TCP connections to the broker, forwards all messages to it,
and then forwards all messages received from the broker to clients through their
WebSocket sessions. Essentially, it acts as a "`relay`" that forwards messages
in both directions.
NOTE: Add `io.projectreactor.netty:reactor-netty` and `io.netty:netty-all`
dependencies to your project for TCP connection management.
@ -2134,7 +2134,8 @@ since that is also an implementation of `WebSocketClient`. The `SockJsClient` ca @@ -2134,7 +2134,8 @@ since that is also an implementation of `WebSocketClient`. The `SockJsClient` ca
use WebSocket or HTTP-based transport as a fallback. For more details, see
<<websocket-fallback-sockjs-client>>.
Next, you can establish a connection and provide a handler for the STOMP session, as the following example shows:
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"]

Loading…
Cancel
Save