Merge branch '5.1.x'
This commit is contained in:
@@ -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;
|
||||
*
|
||||
* <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;
|
||||
* 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) {
|
||||
* ...
|
||||
* }
|
||||
|
||||
@@ -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;
|
||||
|
||||
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.*;
|
||||
*/
|
||||
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"));
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
private static final Resource CONTEXT = qualifiedResource(PrototypeTargetTests.class, "context.xml");
|
||||
|
||||
|
||||
@Test
|
||||
public void testPrototypeProxyWithPrototypeTarget() {
|
||||
TestBeanImpl.constructionCount = 0;
|
||||
@@ -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 {
|
||||
|
||||
|
||||
public static class TestInterceptor implements MethodInterceptor {
|
||||
|
||||
private int invocationCount = 0;
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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;
|
||||
|
||||
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.*;
|
||||
*/
|
||||
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 {
|
||||
|
||||
|
||||
class InvocationCheckExposedInvocationTestBean extends ExposedInvocationTestBean {
|
||||
|
||||
@Override
|
||||
protected void assertions(MethodInvocation invocation) {
|
||||
assertTrue(invocation.getThis() == this);
|
||||
|
||||
@@ -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;
|
||||
|
||||
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.*;
|
||||
*/
|
||||
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 {
|
||||
@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"));
|
||||
|
||||
@@ -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.*;
|
||||
public class RegexpMethodPointcutAdvisorIntegrationTests {
|
||||
|
||||
private static final Resource CONTEXT =
|
||||
qualifiedResource(RegexpMethodPointcutAdvisorIntegrationTests.class, "context.xml");
|
||||
qualifiedResource(RegexpMethodPointcutAdvisorIntegrationTests.class, "context.xml");
|
||||
|
||||
|
||||
@Test
|
||||
public void testSinglePattern() throws Throwable {
|
||||
|
||||
@@ -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;
|
||||
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.*;
|
||||
*/
|
||||
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 {
|
||||
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 {
|
||||
|
||||
// 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 {
|
||||
assertEquals(sp1.getName(), p.getName());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
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.*;
|
||||
*/
|
||||
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 {
|
||||
assertEquals(INITIAL_COUNT, prototype.getCount());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
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.*;
|
||||
*/
|
||||
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 {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
|
||||
@@ -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.*;
|
||||
*/
|
||||
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 {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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++) {
|
||||
|
||||
@@ -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;
|
||||
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.*;
|
||||
*/
|
||||
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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
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.*;
|
||||
*/
|
||||
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 {
|
||||
@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]);
|
||||
|
||||
@@ -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;
|
||||
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.*;
|
||||
*/
|
||||
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 {
|
||||
}
|
||||
|
||||
@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 {
|
||||
}
|
||||
|
||||
@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());
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
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.*;
|
||||
*/
|
||||
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 {
|
||||
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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
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.*;
|
||||
*/
|
||||
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 {
|
||||
|
||||
|
||||
@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");
|
||||
|
||||
@@ -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
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@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
|
||||
|
||||
@@ -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;
|
||||
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;
|
||||
* 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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
(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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
/**
|
||||
* 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,
|
||||
|
||||
@@ -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
|
||||
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static class BeanWithNoDefaultConstructor {
|
||||
|
||||
private final String property1;
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Deserializer extends StdDeserializer<TestObject> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
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 {
|
||||
this.objectMapper = new ObjectMapper(this.jsonFactory);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void doNotTokenizeArrayElements() {
|
||||
testTokenize(
|
||||
@@ -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 {
|
||||
@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 {
|
||||
|
||||
|
||||
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 {
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static class JSONAssertConsumer implements Consumer<String> {
|
||||
|
||||
private final String expected;
|
||||
@@ -253,4 +255,5 @@ public class Jackson2TokenizerTests extends AbstractLeakCheckingTestCase {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -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
|
||||
`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`:
|
||||
----
|
||||
|
||||
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:
|
||||
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:
|
||||
|
||||
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
|
||||
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).
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
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 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>>.
|
||||
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.
|
||||
* 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
|
||||
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
|
||||
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
|
||||
@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
|
||||
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
|
||||
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:
|
||||
----
|
||||
|
||||
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
|
||||
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:
|
||||
</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
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
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:
|
||||
----
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
== 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.
|
||||
== 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:
|
||||
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
|
||||
* 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:
|
||||
----
|
||||
|
||||
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[]
|
||||
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[]
|
||||
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:
|
||||
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.
|
||||
[[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
|
||||
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.
|
||||
|
||||
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
|
||||
[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
|
||||
@Configuration
|
||||
@EnableSpringConfigured
|
||||
public class AppConfig {
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -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
|
||||
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
|
||||
==== 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:
|
||||
}
|
||||
----
|
||||
|
||||
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
|
||||
</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
|
||||
----
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
----
|
||||
|
||||
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:
|
||||
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.
|
||||
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
|
||||
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
|
||||
@Configuration
|
||||
@EnableLoadTimeWeaving
|
||||
public class AppConfig {
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -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
|
||||
`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
|
||||
when you use Spring's LTW support in environments such as application servers and web
|
||||
containers.
|
||||
|
||||
[[aop-aj-ltw-environment-tomcat]]
|
||||
===== Tomcat
|
||||
[[aop-aj-ltw-environments-tomcat-jboss-etc]]
|
||||
===== Tomcat, JBoss, WebSphere, WebLogic
|
||||
|
||||
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.
|
||||
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`.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
<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.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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):
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[xsd-schemas-util-constant]]
|
||||
==== Using `<util:constant/>`
|
||||
|
||||
@@ -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
|
||||
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
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[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
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[xsd-schemas-util-list]]
|
||||
==== Using `<util:list/>`
|
||||
|
||||
@@ -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:
|
||||
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:
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[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>>.
|
||||
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).
|
||||
----
|
||||
<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>>.
|
||||
|
||||
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:
|
||||
* `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`.
|
||||
<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.
|
||||
|
||||
[[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
|
||||
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
|
||||
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:
|
||||
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:
|
||||
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
|
||||
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
|
||||
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:
|
||||
</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
|
||||
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`:
|
||||
}
|
||||
factory.addPropertyValue("children", children);
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -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
|
||||
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:
|
||||
}
|
||||
----
|
||||
|
||||
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`:
|
||||
}
|
||||
return beanName;
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
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:
|
||||
|
||||
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.
|
||||
****
|
||||
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
|
||||
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.
|
||||
[[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:
|
||||
|
||||
* 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].
|
||||
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
|
||||
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.
|
||||
[[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:
|
||||
----
|
||||
<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,
|
||||
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:
|
||||
|
||||
[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
|
||||
=== 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
|
||||
====
|
||||
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:
|
||||
}
|
||||
----
|
||||
|
||||
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):
|
||||
|
||||
`@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:
|
||||
----
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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:
|
||||
===== `@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.
|
||||
[[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
|
||||
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=
|
||||
|
||||
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
|
||||
`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
|
||||
`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`
|
||||
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
|
||||
[[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
|
||||
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:
|
||||
}
|
||||
----
|
||||
|
||||
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
|
||||
}
|
||||
----
|
||||
|
||||
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.
|
||||
==== 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.
|
||||
[[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
|
||||
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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
|
||||
|
||||
[[codecs]]
|
||||
== Codecs
|
||||
|
||||
@@ -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
|
||||
== 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.
|
||||
|
||||
|
||||
@@ -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
|
||||
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:
|
||||
|
||||
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.
|
||||
[[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().
|
||||
|
||||
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:
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
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.
|
||||
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 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.
|
||||
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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
[[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:
|
||||
|
||||
(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.
|
||||
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
|
||||
|
||||
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
|
||||
----
|
||||
|
||||
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.
|
||||
<<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`.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
----
|
||||
|
||||
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
|
||||
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.
|
||||
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:
|
||||
* 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:
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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:
|
||||
</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:
|
||||
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.
|
||||
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.
|
||||
| `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.
|
||||
===== 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:
|
||||
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
|
||||
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.
|
||||
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
|
||||
|
||||
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:
|
||||
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.
|
||||
[[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.
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
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.
|
||||
[[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
|
||||
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
|
||||
====
|
||||
`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
|
||||
[[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.
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
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
|
||||
public interface Messenger {
|
||||
|
||||
String getMessage();
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -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:
|
||||
class GroovyMessenger implements Messenger {
|
||||
|
||||
String message
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -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
|
||||
</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.
|
||||
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
|
||||
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.
|
||||
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:
|
||||
|
||||
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:
|
||||
}
|
||||
----
|
||||
|
||||
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
|
||||
}
|
||||
----
|
||||
|
||||
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
|
||||
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
|
||||
example.)
|
||||
|
||||
|
||||
|
||||
[[dynamic-language-beans-ctor-injection]]
|
||||
==== Understanding Constructor Injection in the Context of Dynamic-language-backed Beans
|
||||
|
||||
@@ -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
|
||||
|
||||
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,
|
||||
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
|
||||
public interface Calculator {
|
||||
|
||||
int add(int x, int y);
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -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:
|
||||
----
|
||||
|
||||
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:
|
||||
}
|
||||
----
|
||||
|
||||
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:
|
||||
|
||||
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`.
|
||||
|
||||
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.`"
|
||||
|
||||
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:
|
||||
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
|
||||
}
|
||||
----
|
||||
|
||||
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.
|
||||
|
||||
|
||||
|
||||
|
||||
[[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:
|
||||
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
|
||||
(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
|
||||
}
|
||||
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
|
||||
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.
|
||||
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>>:
|
||||
</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:
|
||||
|
||||
|
||||
|
||||
|
||||
[[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
|
||||
|
||||
@@ -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>>.
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
|
||||
|
||||
[[kotlin-null-safety]]
|
||||
== Null-safety
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
|
||||
|
||||
[[kotlin-classes-interfaces]]
|
||||
== Classes and Interfaces
|
||||
|
||||
@@ -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].
|
||||
|
||||
|
||||
|
||||
|
||||
[[kotlin-bean-definition-dsl]]
|
||||
== Bean Definition DSL
|
||||
|
||||
@@ -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).
|
||||
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) {
|
||||
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") {
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
|
||||
=== 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
|
||||
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.
|
||||
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
|
||||
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
|
||||
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
|
||||
)
|
||||
----
|
||||
|
||||
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:
|
||||
=== 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:
|
||||
}
|
||||
----
|
||||
|
||||
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:
|
||||
|
||||
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
|
||||
----
|
||||
|
||||
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.
|
||||
|
||||
=== 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(
|
||||
|
||||
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 {
|
||||
----
|
||||
|
||||
|
||||
|
||||
==== Specification-like Tests
|
||||
|
||||
You can create specification-like tests with JUnit 5 and Kotlin.
|
||||
@@ -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
|
||||
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.
|
||||
|
||||
|
||||
|
||||
|
||||
[[kotlin-resources]]
|
||||
== Resources
|
||||
|
||||
@@ -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
|
||||
** 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]
|
||||
|
||||
|
||||
@@ -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
|
||||
"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+.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
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.
|
||||
=== 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:
|
||||
<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
|
||||
[[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:
|
||||
[[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.
|
||||
|
||||
@@ -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.)
|
||||
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:
|
||||
|
||||
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
|
||||
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:
|
||||
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
|
||||
|
||||
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:
|
||||
* 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
|
||||
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:
|
||||
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.
|
||||
|
||||
[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>>.
|
||||
[[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:
|
||||
|
||||
`@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:
|
||||
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
|
||||
==== 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:
|
||||
==== 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.
|
||||
|
||||
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.
|
||||
|
||||
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:
|
||||
==== 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
|
||||
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
|
||||
|
||||
===== `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:
|
||||
|
||||
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.
|
||||
===== 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
|
||||
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:
|
||||
|
||||
|
||||
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:
|
||||
===== 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.
|
||||
--
|
||||
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:
|
||||
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
|
||||
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
|
||||
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 `
|
||||
[[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:
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
`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
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
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`,
|
||||
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.
|
||||
[[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.
|
||||
[[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:
|
||||
----
|
||||
|
||||
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:
|
||||
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.
|
||||
====== 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
|
||||
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:
|
||||
|
||||
@@ -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]
|
||||
|
||||
[[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.
|
||||
`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
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -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.
|
||||
== 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
|
||||
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.
|
||||
[[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.
|
||||
[[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
|
||||
[[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`:
|
||||
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].
|
||||
[[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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
[[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.
|
||||
|
||||
[[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:
|
||||
|
||||
[[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 {
|
||||
|
||||
[[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 {
|
||||
|
||||
[[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
|
||||
|
||||
@@ -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
|
||||
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
|
||||
[[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 {
|
||||
|
||||
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:
|
||||
* `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
|
||||
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.
|
||||
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`>>.
|
||||
|
||||
@@ -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>>.
|
||||
|
||||
[[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
|
||||
|
||||
[[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.
|
||||
|
||||
[[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
|
||||
|
||||
[[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.
|
||||
|
||||
[[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
|
||||
|
||||
[[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].
|
||||
|
||||
[[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.
|
||||
|
||||
[[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,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:
|
||||
* `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"]
|
||||
|
||||
@@ -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]
|
||||
|
||||
[[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.
|
||||
|
||||
[[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 {
|
||||
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 {
|
||||
|
||||
`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
|
||||
|
||||
[[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`.
|
||||
|
||||
[[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.
|
||||
|
||||
[[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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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:
|
||||
* 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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
[[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.
|
||||
|
||||
[[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
|
||||
|
||||
[[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 {
|
||||
|
||||
[[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.
|
||||
|
||||
[[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:
|
||||
|
||||
[[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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
[[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.
|
||||
|
||||
[[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
|
||||
|
||||
[[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:
|
||||
|
||||
[[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
|
||||
|
||||
[[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].
|
||||
|
||||
[[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:
|
||||
|
||||
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
|
||||
|
||||
[[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.
|
||||
|
||||
[[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.
|
||||
|
||||
[[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`
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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]
|
||||
|
||||
[[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.
|
||||
|
||||
[[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
|
||||
</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
|
||||
|
||||
[[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:
|
||||
|
||||
[[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
|
||||
|
||||
[[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
|
||||
----
|
||||
|
||||
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
|
||||
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
|
||||
}
|
||||
----
|
||||
|
||||
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,
|
||||
registry.setApplicationDestinationPrefixes("/app");
|
||||
registry.enableSimpleBroker("/topic");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Controller
|
||||
@@ -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
|
||||
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>>.
|
||||
|
||||
`@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
|
||||
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
|
||||
});
|
||||
----
|
||||
|
||||
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:
|
||||
}
|
||||
----
|
||||
|
||||
`@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
|
||||
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
|
||||
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"]
|
||||
|
||||
Reference in New Issue
Block a user