diff --git a/spring-context/src/main/java/org/springframework/ejb/access/AbstractRemoteSlsbInvokerInterceptor.java b/spring-context/src/main/java/org/springframework/ejb/access/AbstractRemoteSlsbInvokerInterceptor.java index aea7f9a7bb..1a294ffc9a 100644 --- a/spring-context/src/main/java/org/springframework/ejb/access/AbstractRemoteSlsbInvokerInterceptor.java +++ b/spring-context/src/main/java/org/springframework/ejb/access/AbstractRemoteSlsbInvokerInterceptor.java @@ -29,7 +29,6 @@ import org.aopalliance.intercept.MethodInvocation; import org.springframework.lang.Nullable; import org.springframework.remoting.RemoteConnectFailureException; import org.springframework.remoting.RemoteLookupFailureException; -import org.springframework.remoting.rmi.RmiClientInterceptorUtils; /** * Base class for interceptors proxying remote Stateless Session Beans. @@ -121,8 +120,9 @@ public abstract class AbstractRemoteSlsbInvokerInterceptor extends AbstractSlsbI * @return whether the exception should be treated as connect failure * @see org.springframework.remoting.rmi.RmiClientInterceptorUtils#isConnectFailure */ + @SuppressWarnings("deprecation") protected boolean isConnectFailure(RemoteException ex) { - return RmiClientInterceptorUtils.isConnectFailure(ex); + return org.springframework.remoting.rmi.RmiClientInterceptorUtils.isConnectFailure(ex); } @Nullable diff --git a/spring-context/src/main/java/org/springframework/ejb/access/SimpleRemoteSlsbInvokerInterceptor.java b/spring-context/src/main/java/org/springframework/ejb/access/SimpleRemoteSlsbInvokerInterceptor.java index 14eb238e5b..292ddb6409 100644 --- a/spring-context/src/main/java/org/springframework/ejb/access/SimpleRemoteSlsbInvokerInterceptor.java +++ b/spring-context/src/main/java/org/springframework/ejb/access/SimpleRemoteSlsbInvokerInterceptor.java @@ -28,7 +28,6 @@ import org.aopalliance.intercept.MethodInvocation; import org.springframework.beans.factory.DisposableBean; import org.springframework.lang.Nullable; import org.springframework.remoting.RemoteLookupFailureException; -import org.springframework.remoting.rmi.RmiClientInterceptorUtils; /** * Basic invoker for a remote Stateless Session Bean. @@ -95,11 +94,12 @@ public class SimpleRemoteSlsbInvokerInterceptor extends AbstractRemoteSlsbInvoke */ @Override @Nullable + @SuppressWarnings("deprecation") protected Object doInvoke(MethodInvocation invocation) throws Throwable { Object ejb = null; try { ejb = getSessionBeanInstance(); - return RmiClientInterceptorUtils.invokeRemoteMethod(invocation, ejb); + return org.springframework.remoting.rmi.RmiClientInterceptorUtils.invokeRemoteMethod(invocation, ejb); } catch (NamingException ex) { throw new RemoteLookupFailureException("Failed to locate remote EJB [" + getJndiName() + "]", ex); @@ -108,12 +108,12 @@ public class SimpleRemoteSlsbInvokerInterceptor extends AbstractRemoteSlsbInvoke Throwable targetEx = ex.getTargetException(); if (targetEx instanceof RemoteException) { RemoteException rex = (RemoteException) targetEx; - throw RmiClientInterceptorUtils.convertRmiAccessException( - invocation.getMethod(), rex, isConnectFailure(rex), getJndiName()); + throw org.springframework.remoting.rmi.RmiClientInterceptorUtils.convertRmiAccessException( + invocation.getMethod(), rex, isConnectFailure(rex), getJndiName()); } else if (targetEx instanceof CreateException) { - throw RmiClientInterceptorUtils.convertRmiAccessException( - invocation.getMethod(), targetEx, "Could not create remote EJB [" + getJndiName() + "]"); + throw org.springframework.remoting.rmi.RmiClientInterceptorUtils.convertRmiAccessException( + invocation.getMethod(), targetEx, "Could not create remote EJB [" + getJndiName() + "]"); } throw targetEx; } diff --git a/spring-context/src/main/java/org/springframework/remoting/rmi/CodebaseAwareObjectInputStream.java b/spring-context/src/main/java/org/springframework/remoting/rmi/CodebaseAwareObjectInputStream.java index 8a95fb8153..0244db024f 100644 --- a/spring-context/src/main/java/org/springframework/remoting/rmi/CodebaseAwareObjectInputStream.java +++ b/spring-context/src/main/java/org/springframework/remoting/rmi/CodebaseAwareObjectInputStream.java @@ -50,7 +50,9 @@ import org.springframework.lang.Nullable; * @see java.rmi.server.RMIClassLoader * @see RemoteInvocationSerializingExporter#createObjectInputStream * @see org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor#setCodebaseUrl + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public class CodebaseAwareObjectInputStream extends ConfigurableObjectInputStream { private final String codebaseUrl; diff --git a/spring-context/src/main/java/org/springframework/remoting/rmi/JndiRmiClientInterceptor.java b/spring-context/src/main/java/org/springframework/remoting/rmi/JndiRmiClientInterceptor.java index 163eb97f84..15ff27c655 100644 --- a/spring-context/src/main/java/org/springframework/remoting/rmi/JndiRmiClientInterceptor.java +++ b/spring-context/src/main/java/org/springframework/remoting/rmi/JndiRmiClientInterceptor.java @@ -72,7 +72,9 @@ import org.springframework.util.Assert; * @see org.springframework.remoting.RemoteAccessException * @see java.rmi.RemoteException * @see java.rmi.Remote + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public class JndiRmiClientInterceptor extends JndiObjectLocator implements MethodInterceptor, InitializingBean { private Class serviceInterface; diff --git a/spring-context/src/main/java/org/springframework/remoting/rmi/JndiRmiProxyFactoryBean.java b/spring-context/src/main/java/org/springframework/remoting/rmi/JndiRmiProxyFactoryBean.java index 6a5d164fd5..6253240502 100644 --- a/spring-context/src/main/java/org/springframework/remoting/rmi/JndiRmiProxyFactoryBean.java +++ b/spring-context/src/main/java/org/springframework/remoting/rmi/JndiRmiProxyFactoryBean.java @@ -61,7 +61,9 @@ import org.springframework.util.ClassUtils; * @see java.rmi.RemoteException * @see java.rmi.Remote * @see javax.rmi.PortableRemoteObject#narrow + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public class JndiRmiProxyFactoryBean extends JndiRmiClientInterceptor implements FactoryBean, BeanClassLoaderAware { diff --git a/spring-context/src/main/java/org/springframework/remoting/rmi/JndiRmiServiceExporter.java b/spring-context/src/main/java/org/springframework/remoting/rmi/JndiRmiServiceExporter.java index b2bafa7799..df438337da 100644 --- a/spring-context/src/main/java/org/springframework/remoting/rmi/JndiRmiServiceExporter.java +++ b/spring-context/src/main/java/org/springframework/remoting/rmi/JndiRmiServiceExporter.java @@ -67,7 +67,9 @@ import org.springframework.util.ReflectionUtils; * @see JndiRmiClientInterceptor * @see JndiRmiProxyFactoryBean * @see javax.rmi.PortableRemoteObject#exportObject + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public class JndiRmiServiceExporter extends RmiBasedExporter implements InitializingBean, DisposableBean { @Nullable diff --git a/spring-context/src/main/java/org/springframework/remoting/rmi/RemoteInvocationSerializingExporter.java b/spring-context/src/main/java/org/springframework/remoting/rmi/RemoteInvocationSerializingExporter.java index ef0c4453dc..76e588803d 100644 --- a/spring-context/src/main/java/org/springframework/remoting/rmi/RemoteInvocationSerializingExporter.java +++ b/spring-context/src/main/java/org/springframework/remoting/rmi/RemoteInvocationSerializingExporter.java @@ -45,7 +45,9 @@ import org.springframework.util.ClassUtils; * @see java.io.ObjectOutputStream * @see #doReadRemoteInvocation * @see #doWriteRemoteInvocationResult + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public abstract class RemoteInvocationSerializingExporter extends RemoteInvocationBasedExporter implements InitializingBean { diff --git a/spring-context/src/main/java/org/springframework/remoting/rmi/RmiBasedExporter.java b/spring-context/src/main/java/org/springframework/remoting/rmi/RmiBasedExporter.java index 504ec943eb..c7bfd501e7 100644 --- a/spring-context/src/main/java/org/springframework/remoting/rmi/RmiBasedExporter.java +++ b/spring-context/src/main/java/org/springframework/remoting/rmi/RmiBasedExporter.java @@ -36,7 +36,9 @@ import org.springframework.remoting.support.RemoteInvocationBasedExporter; * @since 1.2.5 * @see RmiServiceExporter * @see JndiRmiServiceExporter + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public abstract class RmiBasedExporter extends RemoteInvocationBasedExporter { /** diff --git a/spring-context/src/main/java/org/springframework/remoting/rmi/RmiClientInterceptor.java b/spring-context/src/main/java/org/springframework/remoting/rmi/RmiClientInterceptor.java index 8279186a8c..bbb263b3a6 100644 --- a/spring-context/src/main/java/org/springframework/remoting/rmi/RmiClientInterceptor.java +++ b/spring-context/src/main/java/org/springframework/remoting/rmi/RmiClientInterceptor.java @@ -67,7 +67,9 @@ import org.springframework.remoting.support.RemoteInvocationUtils; * @see org.springframework.remoting.RemoteAccessException * @see java.rmi.RemoteException * @see java.rmi.Remote + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public class RmiClientInterceptor extends RemoteInvocationBasedAccessor implements MethodInterceptor { diff --git a/spring-context/src/main/java/org/springframework/remoting/rmi/RmiClientInterceptorUtils.java b/spring-context/src/main/java/org/springframework/remoting/rmi/RmiClientInterceptorUtils.java index 37b161a482..4c8e57b795 100644 --- a/spring-context/src/main/java/org/springframework/remoting/rmi/RmiClientInterceptorUtils.java +++ b/spring-context/src/main/java/org/springframework/remoting/rmi/RmiClientInterceptorUtils.java @@ -44,7 +44,9 @@ import org.springframework.util.ReflectionUtils; * * @author Juergen Hoeller * @since 1.1 + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public abstract class RmiClientInterceptorUtils { private static final Log logger = LogFactory.getLog(RmiClientInterceptorUtils.class); diff --git a/spring-context/src/main/java/org/springframework/remoting/rmi/RmiInvocationHandler.java b/spring-context/src/main/java/org/springframework/remoting/rmi/RmiInvocationHandler.java index a2bb4a26c1..b10f6db004 100644 --- a/spring-context/src/main/java/org/springframework/remoting/rmi/RmiInvocationHandler.java +++ b/spring-context/src/main/java/org/springframework/remoting/rmi/RmiInvocationHandler.java @@ -32,7 +32,9 @@ import org.springframework.remoting.support.RemoteInvocation; * * @author Juergen Hoeller * @since 14.05.2003 + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public interface RmiInvocationHandler extends Remote { /** diff --git a/spring-context/src/main/java/org/springframework/remoting/rmi/RmiInvocationWrapper.java b/spring-context/src/main/java/org/springframework/remoting/rmi/RmiInvocationWrapper.java index 4ff3a29128..1f030b327c 100644 --- a/spring-context/src/main/java/org/springframework/remoting/rmi/RmiInvocationWrapper.java +++ b/spring-context/src/main/java/org/springframework/remoting/rmi/RmiInvocationWrapper.java @@ -34,6 +34,7 @@ import org.springframework.util.Assert; * @since 14.05.2003 * @see RmiServiceExporter */ +@Deprecated class RmiInvocationWrapper implements RmiInvocationHandler { private final Object wrappedObject; diff --git a/spring-context/src/main/java/org/springframework/remoting/rmi/RmiProxyFactoryBean.java b/spring-context/src/main/java/org/springframework/remoting/rmi/RmiProxyFactoryBean.java index a411574a29..b8b894d9b5 100644 --- a/spring-context/src/main/java/org/springframework/remoting/rmi/RmiProxyFactoryBean.java +++ b/spring-context/src/main/java/org/springframework/remoting/rmi/RmiProxyFactoryBean.java @@ -57,7 +57,9 @@ import org.springframework.util.Assert; * @see org.springframework.remoting.RemoteAccessException * @see org.springframework.remoting.caucho.HessianProxyFactoryBean * @see org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public class RmiProxyFactoryBean extends RmiClientInterceptor implements FactoryBean, BeanClassLoaderAware { private Object serviceProxy; diff --git a/spring-context/src/main/java/org/springframework/remoting/rmi/RmiRegistryFactoryBean.java b/spring-context/src/main/java/org/springframework/remoting/rmi/RmiRegistryFactoryBean.java index f8a8a72409..2a8f06a36d 100644 --- a/spring-context/src/main/java/org/springframework/remoting/rmi/RmiRegistryFactoryBean.java +++ b/spring-context/src/main/java/org/springframework/remoting/rmi/RmiRegistryFactoryBean.java @@ -60,7 +60,9 @@ import org.springframework.lang.Nullable; * @see org.springframework.jmx.support.ConnectorServerFactoryBean * @see java.rmi.registry.Registry * @see java.rmi.registry.LocateRegistry + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public class RmiRegistryFactoryBean implements FactoryBean, InitializingBean, DisposableBean { protected final Log logger = LogFactory.getLog(getClass()); diff --git a/spring-context/src/main/java/org/springframework/remoting/rmi/RmiServiceExporter.java b/spring-context/src/main/java/org/springframework/remoting/rmi/RmiServiceExporter.java index 68ccd05898..1b32e4279b 100644 --- a/spring-context/src/main/java/org/springframework/remoting/rmi/RmiServiceExporter.java +++ b/spring-context/src/main/java/org/springframework/remoting/rmi/RmiServiceExporter.java @@ -65,7 +65,9 @@ import org.springframework.lang.Nullable; * @see java.rmi.RemoteException * @see org.springframework.remoting.caucho.HessianServiceExporter * @see org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public class RmiServiceExporter extends RmiBasedExporter implements InitializingBean, DisposableBean { private String serviceName; diff --git a/spring-jms/src/main/java/org/springframework/jms/remoting/JmsInvokerClientInterceptor.java b/spring-jms/src/main/java/org/springframework/jms/remoting/JmsInvokerClientInterceptor.java index eb918b44b0..a9c94342e8 100644 --- a/spring-jms/src/main/java/org/springframework/jms/remoting/JmsInvokerClientInterceptor.java +++ b/spring-jms/src/main/java/org/springframework/jms/remoting/JmsInvokerClientInterceptor.java @@ -71,7 +71,9 @@ import org.springframework.util.Assert; * @see #setQueueName * @see org.springframework.jms.remoting.JmsInvokerServiceExporter * @see org.springframework.jms.remoting.JmsInvokerProxyFactoryBean + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public class JmsInvokerClientInterceptor implements MethodInterceptor, InitializingBean { @Nullable diff --git a/spring-jms/src/main/java/org/springframework/jms/remoting/JmsInvokerProxyFactoryBean.java b/spring-jms/src/main/java/org/springframework/jms/remoting/JmsInvokerProxyFactoryBean.java index df21221b42..2e7d748e4b 100644 --- a/spring-jms/src/main/java/org/springframework/jms/remoting/JmsInvokerProxyFactoryBean.java +++ b/spring-jms/src/main/java/org/springframework/jms/remoting/JmsInvokerProxyFactoryBean.java @@ -41,7 +41,9 @@ import org.springframework.util.ClassUtils; * @see #setServiceInterface * @see org.springframework.jms.remoting.JmsInvokerClientInterceptor * @see org.springframework.jms.remoting.JmsInvokerServiceExporter + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public class JmsInvokerProxyFactoryBean extends JmsInvokerClientInterceptor implements FactoryBean, BeanClassLoaderAware { diff --git a/spring-jms/src/main/java/org/springframework/jms/remoting/JmsInvokerServiceExporter.java b/spring-jms/src/main/java/org/springframework/jms/remoting/JmsInvokerServiceExporter.java index 6bcb1f0b94..ced31131b9 100644 --- a/spring-jms/src/main/java/org/springframework/jms/remoting/JmsInvokerServiceExporter.java +++ b/spring-jms/src/main/java/org/springframework/jms/remoting/JmsInvokerServiceExporter.java @@ -51,7 +51,9 @@ import org.springframework.remoting.support.RemoteInvocationResult; * @since 2.0 * @see JmsInvokerClientInterceptor * @see JmsInvokerProxyFactoryBean + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public class JmsInvokerServiceExporter extends RemoteInvocationBasedExporter implements SessionAwareMessageListener, InitializingBean { diff --git a/spring-web/src/main/java/org/springframework/remoting/caucho/HessianClientInterceptor.java b/spring-web/src/main/java/org/springframework/remoting/caucho/HessianClientInterceptor.java index 9808424104..f934e877db 100644 --- a/spring-web/src/main/java/org/springframework/remoting/caucho/HessianClientInterceptor.java +++ b/spring-web/src/main/java/org/springframework/remoting/caucho/HessianClientInterceptor.java @@ -63,7 +63,9 @@ import org.springframework.util.Assert; * @see HessianProxyFactoryBean * @see com.caucho.hessian.client.HessianProxyFactory * @see com.caucho.hessian.server.HessianServlet + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public class HessianClientInterceptor extends UrlBasedRemoteAccessor implements MethodInterceptor { private HessianProxyFactory proxyFactory = new HessianProxyFactory(); diff --git a/spring-web/src/main/java/org/springframework/remoting/caucho/HessianExporter.java b/spring-web/src/main/java/org/springframework/remoting/caucho/HessianExporter.java index 5344d77151..7e865c0dd6 100644 --- a/spring-web/src/main/java/org/springframework/remoting/caucho/HessianExporter.java +++ b/spring-web/src/main/java/org/springframework/remoting/caucho/HessianExporter.java @@ -53,7 +53,9 @@ import org.springframework.util.CommonsLogWriter; * @since 2.5.1 * @see #invoke(java.io.InputStream, java.io.OutputStream) * @see HessianServiceExporter + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public class HessianExporter extends RemoteExporter implements InitializingBean { /** diff --git a/spring-web/src/main/java/org/springframework/remoting/caucho/HessianProxyFactoryBean.java b/spring-web/src/main/java/org/springframework/remoting/caucho/HessianProxyFactoryBean.java index 39d2d6aa0a..c03a9d081c 100644 --- a/spring-web/src/main/java/org/springframework/remoting/caucho/HessianProxyFactoryBean.java +++ b/spring-web/src/main/java/org/springframework/remoting/caucho/HessianProxyFactoryBean.java @@ -40,7 +40,9 @@ import org.springframework.lang.Nullable; * @see HessianServiceExporter * @see org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean * @see org.springframework.remoting.rmi.RmiProxyFactoryBean + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public class HessianProxyFactoryBean extends HessianClientInterceptor implements FactoryBean { @Nullable diff --git a/spring-web/src/main/java/org/springframework/remoting/caucho/HessianServiceExporter.java b/spring-web/src/main/java/org/springframework/remoting/caucho/HessianServiceExporter.java index 1ac88871f0..d1efeca08c 100644 --- a/spring-web/src/main/java/org/springframework/remoting/caucho/HessianServiceExporter.java +++ b/spring-web/src/main/java/org/springframework/remoting/caucho/HessianServiceExporter.java @@ -44,7 +44,9 @@ import org.springframework.web.util.NestedServletException; * @see HessianProxyFactoryBean * @see org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter * @see org.springframework.remoting.rmi.RmiServiceExporter + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public class HessianServiceExporter extends HessianExporter implements HttpRequestHandler { /** diff --git a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/AbstractHttpInvokerRequestExecutor.java b/spring-web/src/main/java/org/springframework/remoting/httpinvoker/AbstractHttpInvokerRequestExecutor.java index 790d63ea89..3f3fb9df1c 100644 --- a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/AbstractHttpInvokerRequestExecutor.java +++ b/spring-web/src/main/java/org/springframework/remoting/httpinvoker/AbstractHttpInvokerRequestExecutor.java @@ -29,7 +29,6 @@ import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.lang.Nullable; -import org.springframework.remoting.rmi.CodebaseAwareObjectInputStream; import org.springframework.remoting.support.RemoteInvocation; import org.springframework.remoting.support.RemoteInvocationResult; import org.springframework.util.Assert; @@ -44,7 +43,9 @@ import org.springframework.util.ClassUtils; * @author Juergen Hoeller * @since 1.1 * @see #doExecuteRequest + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public abstract class AbstractHttpInvokerRequestExecutor implements HttpInvokerRequestExecutor, BeanClassLoaderAware { /** @@ -264,7 +265,7 @@ public abstract class AbstractHttpInvokerRequestExecutor implements HttpInvokerR * @see org.springframework.remoting.rmi.CodebaseAwareObjectInputStream */ protected ObjectInputStream createObjectInputStream(InputStream is, @Nullable String codebaseUrl) throws IOException { - return new CodebaseAwareObjectInputStream(is, getBeanClassLoader(), codebaseUrl); + return new org.springframework.remoting.rmi.CodebaseAwareObjectInputStream(is, getBeanClassLoader(), codebaseUrl); } /** diff --git a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpComponentsHttpInvokerRequestExecutor.java b/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpComponentsHttpInvokerRequestExecutor.java index 836628dda9..4056d1abd3 100644 --- a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpComponentsHttpInvokerRequestExecutor.java +++ b/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpComponentsHttpInvokerRequestExecutor.java @@ -60,7 +60,9 @@ import org.springframework.util.Assert; * @author Stephane Nicoll * @since 3.1 * @see org.springframework.remoting.httpinvoker.SimpleHttpInvokerRequestExecutor + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public class HttpComponentsHttpInvokerRequestExecutor extends AbstractHttpInvokerRequestExecutor { private static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 100; diff --git a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerClientConfiguration.java b/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerClientConfiguration.java index c60793749f..4af42c71b3 100644 --- a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerClientConfiguration.java +++ b/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerClientConfiguration.java @@ -25,7 +25,9 @@ import org.springframework.lang.Nullable; * @since 1.1 * @see HttpInvokerRequestExecutor * @see HttpInvokerClientInterceptor + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public interface HttpInvokerClientConfiguration { /** diff --git a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerClientInterceptor.java b/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerClientInterceptor.java index 1233c16666..688fb2c039 100644 --- a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerClientInterceptor.java +++ b/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerClientInterceptor.java @@ -69,7 +69,9 @@ import org.springframework.remoting.support.RemoteInvocationResult; * @see HttpInvokerServiceExporter * @see HttpInvokerProxyFactoryBean * @see java.rmi.server.RMIClassLoader + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public class HttpInvokerClientInterceptor extends RemoteInvocationBasedAccessor implements MethodInterceptor, HttpInvokerClientConfiguration { diff --git a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerProxyFactoryBean.java b/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerProxyFactoryBean.java index 554d74487a..6d1efa52bf 100644 --- a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerProxyFactoryBean.java +++ b/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerProxyFactoryBean.java @@ -53,7 +53,9 @@ import org.springframework.util.Assert; * @see HttpInvokerServiceExporter * @see org.springframework.remoting.rmi.RmiProxyFactoryBean * @see org.springframework.remoting.caucho.HessianProxyFactoryBean + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public class HttpInvokerProxyFactoryBean extends HttpInvokerClientInterceptor implements FactoryBean { @Nullable diff --git a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerRequestExecutor.java b/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerRequestExecutor.java index 963993bdb5..a4f72c9a23 100644 --- a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerRequestExecutor.java +++ b/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerRequestExecutor.java @@ -40,7 +40,9 @@ import org.springframework.remoting.support.RemoteInvocationResult; * @author Juergen Hoeller * @since 1.1 * @see HttpInvokerClientInterceptor#setHttpInvokerRequestExecutor + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated @FunctionalInterface public interface HttpInvokerRequestExecutor { diff --git a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerServiceExporter.java b/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerServiceExporter.java index 3c863d67d7..dc65bd0179 100644 --- a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerServiceExporter.java +++ b/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerServiceExporter.java @@ -27,7 +27,6 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.springframework.remoting.rmi.RemoteInvocationSerializingExporter; import org.springframework.remoting.support.RemoteInvocation; import org.springframework.remoting.support.RemoteInvocationResult; import org.springframework.web.HttpRequestHandler; @@ -58,8 +57,10 @@ import org.springframework.web.util.NestedServletException; * @see HttpInvokerProxyFactoryBean * @see org.springframework.remoting.rmi.RmiServiceExporter * @see org.springframework.remoting.caucho.HessianServiceExporter + * @deprecated as of 5.3.0 with no replacement. */ -public class HttpInvokerServiceExporter extends RemoteInvocationSerializingExporter implements HttpRequestHandler { +@Deprecated +public class HttpInvokerServiceExporter extends org.springframework.remoting.rmi.RemoteInvocationSerializingExporter implements HttpRequestHandler { /** * Reads a remote invocation from the request, executes it, @@ -167,7 +168,7 @@ public class HttpInvokerServiceExporter extends RemoteInvocationSerializingExpor throws IOException { try (ObjectOutputStream oos = - createObjectOutputStream(new FlushGuardedOutputStream(decorateOutputStream(request, response, os)))) { + createObjectOutputStream(new FlushGuardedOutputStream(decorateOutputStream(request, response, os)))) { doWriteRemoteInvocationResult(result, oos); } } diff --git a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/SimpleHttpInvokerRequestExecutor.java b/spring-web/src/main/java/org/springframework/remoting/httpinvoker/SimpleHttpInvokerRequestExecutor.java index bcaa28e5ff..364333ba76 100644 --- a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/SimpleHttpInvokerRequestExecutor.java +++ b/spring-web/src/main/java/org/springframework/remoting/httpinvoker/SimpleHttpInvokerRequestExecutor.java @@ -41,7 +41,9 @@ import org.springframework.remoting.support.RemoteInvocationResult; * @author Juergen Hoeller * @since 1.1 * @see java.net.HttpURLConnection + * @deprecated as of 5.3.0 with no replacement. */ +@Deprecated public class SimpleHttpInvokerRequestExecutor extends AbstractHttpInvokerRequestExecutor { private int connectTimeout = -1; diff --git a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/SimpleHttpInvokerServiceExporter.java b/spring-web/src/main/java/org/springframework/remoting/httpinvoker/SimpleHttpInvokerServiceExporter.java index d5396d75b9..5c8e431fba 100644 --- a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/SimpleHttpInvokerServiceExporter.java +++ b/spring-web/src/main/java/org/springframework/remoting/httpinvoker/SimpleHttpInvokerServiceExporter.java @@ -25,7 +25,6 @@ import java.io.OutputStream; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; -import org.springframework.remoting.rmi.RemoteInvocationSerializingExporter; import org.springframework.remoting.support.RemoteInvocation; import org.springframework.remoting.support.RemoteInvocationResult; @@ -58,7 +57,7 @@ import org.springframework.remoting.support.RemoteInvocationResult; */ @Deprecated @org.springframework.lang.UsesSunHttpServer -public class SimpleHttpInvokerServiceExporter extends RemoteInvocationSerializingExporter implements HttpHandler { +public class SimpleHttpInvokerServiceExporter extends org.springframework.remoting.rmi.RemoteInvocationSerializingExporter implements HttpHandler { /** * Reads a remote invocation from the request, executes it, diff --git a/src/docs/asciidoc/integration.adoc b/src/docs/asciidoc/integration.adoc index bd16cf6667..693182add0 100644 --- a/src/docs/asciidoc/integration.adoc +++ b/src/docs/asciidoc/integration.adoc @@ -10,9 +10,356 @@ :docinfo1: This part of the reference documentation covers the Spring Framework's integration with -a number of Java EE (and related) technologies. +a number technologies. +[[rest-client-access]] +== REST Endpoints + +The Spring Framework provides two choices for making calls to REST endpoints: + +* <>: The original Spring REST client with a synchronous, template +method API. +* <>: a non-blocking, reactive alternative +that supports both synchronous and asynchronous as well as streaming scenarios. + +NOTE: As of 5.0 the `RestTemplate` is in maintenance mode, with only minor requests for +changes and bugs to be accepted going forward. Please, consider using the +<> which offers a more modern API and +supports sync, async, and streaming scenarios. + + +[[rest-resttemplate]] +=== `RestTemplate` + +The `RestTemplate` provides a higher level API over HTTP client libraries. It makes it +easy to invoke REST endpoints in a single line. It exposes the following groups of +overloaded methods: + +[[rest-overview-of-resttemplate-methods-tbl]] +.RestTemplate methods +[cols="1,3"] +|=== +| Method group | Description + +| `getForObject` +| Retrieves a representation via GET. + +| `getForEntity` +| Retrieves a `ResponseEntity` (that is, status, headers, and body) by using GET. + +| `headForHeaders` +| Retrieves all headers for a resource by using HEAD. + +| `postForLocation` +| Creates a new resource by using POST and returns the `Location` header from the response. + +| `postForObject` +| Creates a new resource by using POST and returns the representation from the response. + +| `postForEntity` +| Creates a new resource by using POST and returns the representation from the response. + +| `put` +| Creates or updates a resource by using PUT. + +| `patchForObject` +| Updates a resource by using PATCH and returns the representation from the response. +Note that the JDK `HttpURLConnection` does not support the `PATCH`, but Apache +HttpComponents and others do. + +| `delete` +| Deletes the resources at the specified URI by using DELETE. + +| `optionsForAllow` +| Retrieves allowed HTTP methods for a resource by using ALLOW. + +| `exchange` +| More generalized (and less opinionated) version of the preceding methods that provides extra +flexibility when needed. It accepts a `RequestEntity` (including HTTP method, URL, headers, +and body as input) and returns a `ResponseEntity`. + +These methods allow the use of `ParameterizedTypeReference` instead of `Class` to specify +a response type with generics. + +| `execute` +| The most generalized way to perform a request, with full control over request +preparation and response extraction through callback interfaces. + +|=== + +[[rest-resttemplate-create]] +==== Initialization + +The default constructor uses `java.net.HttpURLConnection` to perform requests. You can +switch to a different HTTP library with an implementation of `ClientHttpRequestFactory`. +There is built-in support for the following: + +* Apache HttpComponents +* Netty +* OkHttp + +For example, to switch to Apache HttpComponents, you can use the following: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory()); +---- + +Each `ClientHttpRequestFactory` exposes configuration options specific to the underlying +HTTP client library -- for example, for credentials, connection pooling, and other details. + +TIP: Note that the `java.net` implementation for HTTP requests can raise an exception when +accessing the status of a response that represents an error (such as 401). If this is an +issue, switch to another HTTP client library. + +[[rest-resttemplate-uri]] +===== URIs + +Many of the `RestTemplate` methods accept a URI template and URI template variables, +either as a `String` variable argument, or as `Map`. + +The following example uses a `String` variable argument: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + String result = restTemplate.getForObject( + "https://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42", "21"); +---- + +The following example uses a `Map`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + Map vars = Collections.singletonMap("hotel", "42"); + + String result = restTemplate.getForObject( + "https://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars); +---- + +Keep in mind URI templates are automatically encoded, as the following example shows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + restTemplate.getForObject("https://example.com/hotel list", String.class); + + // Results in request to "https://example.com/hotel%20list" +---- + +You can use the `uriTemplateHandler` property of `RestTemplate` to customize how URIs +are encoded. Alternatively, you can prepare a `java.net.URI` and pass it into one of +the `RestTemplate` methods that accepts a `URI`. + +For more details on working with and encoding URIs, see <>. + +[[rest-template-headers]] +===== Headers + +You can use the `exchange()` methods to specify request headers, as the following example shows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + String uriTemplate = "https://example.com/hotels/{hotel}"; + URI uri = UriComponentsBuilder.fromUriString(uriTemplate).build(42); + + RequestEntity requestEntity = RequestEntity.get(uri) + .header(("MyRequestHeader", "MyValue") + .build(); + + ResponseEntity response = template.exchange(requestEntity, String.class); + + String responseHeader = response.getHeaders().getFirst("MyResponseHeader"); + String body = response.getBody(); +---- + +You can obtain response headers through many `RestTemplate` method variants that return +`ResponseEntity`. + +[[rest-template-body]] +==== Body + +Objects passed into and returned from `RestTemplate` methods are converted to and from raw +content with the help of an `HttpMessageConverter`. + +On a POST, an input object is serialized to the request body, as the following example shows: + +---- +URI location = template.postForLocation("https://example.com/people", person); +---- + +You need not explicitly set the Content-Type header of the request. In most cases, +you can find a compatible message converter based on the source `Object` type, and the chosen +message converter sets the content type accordingly. If necessary, you can use the +`exchange` methods to explicitly provide the `Content-Type` request header, and that, in +turn, influences what message converter is selected. + +On a GET, the body of the response is deserialized to an output `Object`, as the following example shows: + +---- +Person person = restTemplate.getForObject("https://example.com/people/{id}", Person.class, 42); +---- + +The `Accept` header of the request does not need to be explicitly set. In most cases, +a compatible message converter can be found based on the expected response type, which +then helps to populate the `Accept` header. If necessary, you can use the `exchange` +methods to provide the `Accept` header explicitly. + +By default, `RestTemplate` registers all built-in +<>, depending on classpath checks that help +to determine what optional conversion libraries are present. You can also set the message +converters to use explicitly. + +[[rest-message-conversion]] +==== Message Conversion +[.small]#<># + +The `spring-web` module contains the `HttpMessageConverter` contract for reading and +writing the body of HTTP requests and responses through `InputStream` and `OutputStream`. +`HttpMessageConverter` instances are used on the client side (for example, in the `RestTemplate`) and +on the server side (for example, in Spring MVC REST controllers). + +Concrete implementations for the main media (MIME) types are provided in the framework +and are, by default, registered with the `RestTemplate` on the client side and with +`RequestMethodHandlerAdapter` on the server side (see +<>). + +The implementations of `HttpMessageConverter` are described in the following sections. +For all converters, a default media type is used, but you can override it by setting the +`supportedMediaTypes` bean property. The following table describes each implementation: + +[[rest-message-converters-tbl]] +.HttpMessageConverter Implementations +[cols="1,3"] +|=== +| MessageConverter | Description + +| `StringHttpMessageConverter` +| An `HttpMessageConverter` implementation that can read and write `String` instances from the HTTP +request and response. By default, this converter supports all text media types +(`text/{asterisk}`) and writes with a `Content-Type` of `text/plain`. + +| `FormHttpMessageConverter` +| An `HttpMessageConverter` implementation that can read and write form data from the HTTP +request and response. By default, this converter reads and writes the +`application/x-www-form-urlencoded` media type. Form data is read from and written into a +`MultiValueMap`. The converter can also write (but not read) multipart +data read from a `MultiValueMap`. By default, `multipart/form-data` is +supported. As of Spring Framework 5.2, additional multipart subtypes can be supported for +writing form data. Consult the javadoc for `FormHttpMessageConverter` for further details. + +| `ByteArrayHttpMessageConverter` +| An `HttpMessageConverter` implementation that can read and write byte arrays from the +HTTP request and response. By default, this converter supports all media types (`{asterisk}/{asterisk}`) +and writes with a `Content-Type` of `application/octet-stream`. You can override this +by setting the `supportedMediaTypes` property and overriding `getContentType(byte[])`. + +| `MarshallingHttpMessageConverter` +| An `HttpMessageConverter` implementation that can read and write XML by using Spring's +`Marshaller` and `Unmarshaller` abstractions from the `org.springframework.oxm` package. +This converter requires a `Marshaller` and `Unmarshaller` before it can be used. You can inject these +through constructor or bean properties. By default, this converter supports +`text/xml` and `application/xml`. + +| `MappingJackson2HttpMessageConverter` +| An `HttpMessageConverter` implementation that can read and write JSON by using Jackson's +`ObjectMapper`. You can customize JSON mapping as needed through the use of Jackson's +provided annotations. When you need further control (for cases where custom JSON +serializers/deserializers need to be provided for specific types), you can inject a custom `ObjectMapper` +through the `ObjectMapper` property. By default, this +converter supports `application/json`. + +| `MappingJackson2XmlHttpMessageConverter` +| An `HttpMessageConverter` implementation that can read and write XML by using +https://github.com/FasterXML/jackson-dataformat-xml[Jackson XML] extension's +`XmlMapper`. You can customize XML mapping as needed through the use of JAXB +or Jackson's provided annotations. When you need further control (for cases where custom XML +serializers/deserializers need to be provided for specific types), you can inject a custom `XmlMapper` +through the `ObjectMapper` property. By default, this +converter supports `application/xml`. + +| `SourceHttpMessageConverter` +| An `HttpMessageConverter` implementation that can read and write +`javax.xml.transform.Source` from the HTTP request and response. Only `DOMSource`, +`SAXSource`, and `StreamSource` are supported. By default, this converter supports +`text/xml` and `application/xml`. + +| `BufferedImageHttpMessageConverter` +| An `HttpMessageConverter` implementation that can read and write +`java.awt.image.BufferedImage` from the HTTP request and response. This converter reads +and writes the media type supported by the Java I/O API. + +|=== + +[[rest-template-jsonview]] +==== Jackson JSON Views + +You can specify a https://www.baeldung.com/jackson-json-view-annotation[Jackson JSON View] +to serialize only a subset of the object properties, as the following example shows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + MappingJacksonValue value = new MappingJacksonValue(new User("eric", "7!jd#h23")); + value.setSerializationView(User.WithoutPasswordView.class); + + RequestEntity requestEntity = + RequestEntity.post(new URI("https://example.com/user")).body(value); + + ResponseEntity response = template.exchange(requestEntity, String.class); +---- + +[[rest-template-multipart]] +===== Multipart + +To send multipart data, you need to provide a `MultiValueMap` whose values +may be an `Object` for part content, a `Resource` for a file part, or an `HttpEntity` for +part content with headers. For example: + +[source,java,intent=0] +[subs="verbatim,quotes"] +---- + MultiValueMap parts = new LinkedMultiValueMap<>(); + + parts.add("fieldPart", "fieldValue"); + parts.add("filePart", new FileSystemResource("...logo.png")); + parts.add("jsonPart", new Person("Jason")); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_XML); + parts.add("xmlPart", new HttpEntity<>(myBean, headers)); +---- + +In most cases, you do not have to specify the `Content-Type` for each part. The content +type is determined automatically based on the `HttpMessageConverter` chosen to serialize +it or, in the case of a `Resource` based on the file extension. If necessary, you can +explicitly provide the `MediaType` with an `HttpEntity` wrapper. + +Once the `MultiValueMap` is ready, you can pass it to the `RestTemplate`, as show below: + +[source,java,intent=0] +[subs="verbatim,quotes"] +---- + MultiValueMap parts = ...; + template.postForObject("https://example.com/upload", parts, Void.class); +---- + +If the `MultiValueMap` contains at least one non-`String` value, the `Content-Type` is set +to `multipart/form-data` by the `FormHttpMessageConverter`. If the `MultiValueMap` has +`String` values the `Content-Type` is defaulted to `application/x-www-form-urlencoded`. +If necessary the `Content-Type` may also be set explicitly. + + +[[rest-async-resttemplate]] +=== Using `AsyncRestTemplate` (Deprecated) + +The `AsyncRestTemplate` is deprecated. For all use cases where you might consider using +`AsyncRestTemplate`, use the <> instead. + [[remoting]] @@ -23,6 +370,16 @@ The remoting support eases the development of remote-enabled services, implement via Java interfaces and objects as input and output. Currently, Spring supports the following remoting technologies: +* <>: Spring provides remoting support for web services through JAX-WS. +* <>: Remoting via AMQP as the underlying protocol is supported by the + separate Spring AMQP project. + +WARNING: As of Spring Framework 5.3, support for several remoting technologies is now deprecated +for security reasons and broader industry support. Supporting infrastructure will be removed +from Spring Framework for its next major release. + +The following remoting technologies are now deprecated and will not be replaced: + * <>: Through the use of `RmiProxyFactoryBean` and `RmiServiceExporter`, Spring supports both traditional RMI (with `java.rmi.Remote` interfaces and `java.rmi.RemoteException`) and transparent remoting through RMI @@ -34,12 +391,9 @@ following remoting technologies: * <>: By using Spring's `HessianProxyFactoryBean` and the `HessianServiceExporter`, you can transparently expose your services through the lightweight binary HTTP-based protocol provided by Caucho. -* <>: Spring provides remoting support for web services through JAX-WS. * <>: Remoting via JMS as the underlying protocol is supported through the `JmsInvokerServiceExporter` and `JmsInvokerProxyFactoryBean` classes in the `spring-jms` module. -* <>: Remoting via AMQP as the underlying protocol is supported by the - separate Spring AMQP project. While discussing the remoting capabilities of Spring, we use the following domain model and corresponding services: @@ -94,373 +448,73 @@ the protocol. -[[remoting-rmi]] -=== RMI -By using Spring's support for RMI, you can transparently expose your services through the -RMI infrastructure. After having this set up, you basically have a configuration similar -to remote EJBs, except for the fact that there is no standard support for security -context propagation or remote transaction propagation. Spring does provide hooks for -such additional invocation context when you use the RMI invoker, so you can, for example, -plug in security frameworks or custom security credentials. +[[remoting-amqp]] +=== AMQP +Remoting via AMQP as the underlying protocol is supported in the Spring AMQP project. +For further details please visit the {doc-spring-amqp}/html/#remoting[Spring Remoting] +section of the Spring AMQP reference. - -[[remoting-rmi-server]] -==== Exporting the Service by Using `RmiServiceExporter` - -Using the `RmiServiceExporter`, we can expose the interface of our AccountService object -as RMI object. The interface can be accessed by using `RmiProxyFactoryBean`, or via -plain RMI in case of a traditional RMI service. The `RmiServiceExporter` explicitly -supports the exposing of any non-RMI services via RMI invokers. - -We first have to set up our service in the Spring container. -The following example shows how to do so: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- - -Next, we have to expose our service by using `RmiServiceExporter`. -The following example shows how to do so: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - ----- - -In the preceding example, we override the port for the RMI registry. Often, your application -server also maintains an RMI registry, and it is wise to not interfere with that one. -Furthermore, the service name is used to bind the service. So, in the preceding example, the -service is bound at `'rmi://HOST:1199/AccountService'`. We use this URL later on to link in -the service at the client side. - -NOTE: The `servicePort` property has been omitted (it defaults to 0). This means that an -anonymous port is used to communicate with the service. - - -[[remoting-rmi-client]] -==== Linking in the Service at the Client - -Our client is a simple object that uses the `AccountService` to manage accounts, -as the following example shows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class SimpleObject { - - private AccountService accountService; - - public void setAccountService(AccountService accountService) { - this.accountService = accountService; - } - - // additional methods using the accountService - } ----- - -To link in the service on the client, we create a separate Spring container, -to contain the following simple object and the service linking configuration bits: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - ----- - -That is all we need to do to support the remote account service on the client. Spring -transparently creates an invoker and remotely enables the account service through the -`RmiServiceExporter`. At the client, we link it in by using the `RmiProxyFactoryBean`. - - - -[[remoting-caucho-protocols]] -=== Using Hessian to Remotely Call Services through HTTP - -Hessian offers a binary HTTP-based remoting protocol. It is developed by Caucho, -and you can find more information about Hessian itself at https://www.caucho.com/[]. - - -[[remoting-caucho-protocols-hessian]] -==== Hessian - -Hessian communicates through HTTP and does so by using a custom servlet. By using Spring's -`DispatcherServlet` principles (see <>), we can wire up such a -servlet to expose your services. First, we have to create a new servlet in our application, -as shown in the following excerpt from `web.xml`: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - remoting - org.springframework.web.servlet.DispatcherServlet - 1 - - - - remoting - /remoting/* - ----- - -If you are familiar with Spring's `DispatcherServlet` principles, you probably -know that now you have to create a Spring container configuration resource named -`remoting-servlet.xml` (after the name of your servlet) in the `WEB-INF` directory. -The application context is used in the next section. - -Alternatively, consider the use of Spring's simpler `HttpRequestHandlerServlet`. Doing so -lets you embed the remote exporter definitions in your root application context (by -default, in `WEB-INF/applicationContext.xml`), with individual servlet definitions -pointing to specific exporter beans. In this case, each servlet name needs to match the bean name of -its target exporter. - - -[[remoting-caucho-protocols-hessian-server]] -==== Exposing Your Beans by Using `HessianServiceExporter` - -In the newly created application context called `remoting-servlet.xml`, we create a -`HessianServiceExporter` to export our services, as the following example shows: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - ----- - -Now we are ready to link in the service at the client. No explicit handler mapping is -specified (to map request URLs onto services), so we use `BeanNameUrlHandlerMapping` -used. Hence, the service is exported at the URL indicated through its bean name -within the containing `DispatcherServlet` instance's mapping (as defined earlier): -`https://HOST:8080/remoting/AccountService`. - -Alternatively, you can create a `HessianServiceExporter` in your root application context (for example, -in `WEB-INF/applicationContext.xml`), as the following example shows: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -In the latter case, you should define a corresponding servlet for this exporter in `web.xml`, -with the same end result: The exporter gets mapped to the request path at -`/remoting/AccountService`. Note that the servlet name needs to match the bean name of -the target exporter. The following example shows how to do so: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - accountExporter - org.springframework.web.context.support.HttpRequestHandlerServlet - - - - accountExporter - /remoting/AccountService - ----- - - -[[remoting-caucho-protocols-hessian-client]] -==== Linking in the Service on the Client - -By using the `HessianProxyFactoryBean`, we can link in the service at the client. The same -principles apply as with the RMI example. We create a separate bean factory or -application context and mention the following beans where the `SimpleObject` is by using -the `AccountService` to manage accounts, as the following example shows: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - - ----- - - -[[remoting-caucho-protocols-security]] -==== Applying HTTP Basic Authentication to a Service Exposed through Hessian - -One of the advantages of Hessian is that we can easily apply HTTP basic authentication, -because both protocols are HTTP-based. Your normal HTTP server security mechanism can -be applied through using the `web.xml` security features, for example. Usually, -you need not use per-user security credentials here. Rather, you can use shared credentials that you define -at the `HessianProxyFactoryBean` level (similar to a JDBC `DataSource`), as the following example shows: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - - - - ----- - -In the preceding example, we explicitly mention the `BeanNameUrlHandlerMapping` and set -an interceptor, to let only administrators and operators call the beans mentioned in -this application context. - -NOTE: The preceding example does not show a flexible kind of security infrastructure. For -more options as far as security is concerned, have a look at the Spring Security project -at https://projects.spring.io/spring-security/. - - - -[[remoting-httpinvoker]] -=== Spring HTTP Invoker - -As opposed to Hessian, Spring HTTP invokers are both lightweight protocols that use their own slim -serialization mechanisms and use the standard Java serialization -mechanism to expose services through HTTP. This has a huge advantage if your arguments -and return types are complex types that cannot be serialized by using the serialization -mechanisms Hessian uses (see the next section for more considerations when -you choose a remoting technology). - -Under the hood, Spring uses either the standard facilities provided by the JDK or -Apache `HttpComponents` to perform HTTP calls. If you need more -advanced and easier-to-use functionality, use the latter. See -https://hc.apache.org/httpcomponents-client-ga/[hc.apache.org/httpcomponents-client-ga/] -for more information. - -[WARNING] +[[remoting-autodection-remote-interfaces]] +[NOTE] ==== -Be aware of vulnerabilities due to unsafe Java deserialization: -Manipulated input streams can lead to unwanted code execution on the server -during the deserialization step. As a consequence, do not expose HTTP invoker -endpoints to untrusted clients. Rather, expose them only between your own services. -In general, we strongly recommend using any other message format (such as JSON) instead. +Auto-detection is not implemented for remote interfaces -If you are concerned about security vulnerabilities due to Java serialization, -consider the general-purpose serialization filter mechanism at the core JVM level, -originally developed for JDK 9 but backported to JDK 8, 7 and 6 in the meantime. See -https://blogs.oracle.com/java-platform-group/entry/incoming_filter_serialization_data_a -and https://openjdk.java.net/jeps/290. +The main reason why auto-detection of implemented interfaces does not occur for remote +interfaces is to avoid opening too many doors to remote callers. The target object might +implement internal callback interfaces, such as `InitializingBean` or `DisposableBean` +which one would not want to expose to callers. + +Offering a proxy with all interfaces implemented by the target usually does not matter +in the local case. However, when you export a remote service, you should expose a specific +service interface, with specific operations intended for remote usage. Besides internal +callback interfaces, the target might implement multiple business interfaces, with only +one of them intended for remote exposure. For these reasons, we require such a +service interface to be specified. + +This is a trade-off between configuration convenience and the risk of accidental +exposure of internal methods. Always specifying a service interface is not too much +effort and puts you on the safe side regarding controlled exposure of specific methods. ==== -[[remoting-httpinvoker-server]] -==== Exposing the Service Object -Setting up the HTTP invoker infrastructure for a service object closely resembles the -way you would do the same by using Hessian. As Hessian support provides -`HessianServiceExporter`, Spring's HttpInvoker support provides -`org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter`. +[[remoting-considerations]] +=== Considerations when Choosing a Technology -To expose the `AccountService` (mentioned earlier) within a Spring Web MVC -`DispatcherServlet`, the following configuration needs to be in place in the -dispatcher's application context, as the following example shows: +Each and every technology presented here has its drawbacks. When choosing a technology, +you should carefully consider your needs, the services you expose, and the objects you +send over the wire. -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- +When using RMI, you cannot access the objects through the HTTP protocol, +unless you tunnel the RMI traffic. RMI is a fairly heavy-weight protocol, in that it +supports full-object serialization, which is important when you use a complex data model +that needs serialization over the wire. However, RMI-JRMP is tied to Java clients. It is +a Java-to-Java remoting solution. -Such an exporter definition is exposed through the `DispatcherServlet` instance's standard -mapping facilities, as explained in <>. +Spring's HTTP invoker is a good choice if you need HTTP-based remoting but also rely on +Java serialization. It shares the basic infrastructure with RMI invokers but uses +HTTP as transport. Note that HTTP invokers are not limited only to Java-to-Java remoting +but also to Spring on both the client and the server side. (The latter also applies to +Spring's RMI invoker for non-RMI interfaces.) -Alternatively, you can create an `HttpInvokerServiceExporter` in your root application context -(for example, in `'WEB-INF/applicationContext.xml'`), as the following example shows: +Hessian might provide significant value when operating in a heterogeneous environment, +because they explicitly allow for non-Java clients. However, non-Java support is still +limited. Known issues include the serialization of Hibernate objects in combination with +lazily-initialized collections. If you have such a data model, consider using RMI or +HTTP invokers instead of Hessian. -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- +JMS can be useful for providing clusters of services and letting the JMS broker take +care of load balancing, discovery, and auto-failover. By default, Java serialization is +used for JMS remoting, but the JMS provider could use a different mechanism for +the wire formatting, such as XStream to let servers be implemented in other +technologies. -In addition, you can define a corresponding servlet for this exporter in `web.xml`, with the -servlet name matching the bean name of the target exporter, as the following example shows: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - accountExporter - org.springframework.web.context.support.HttpRequestHandlerServlet - - - - accountExporter - /remoting/AccountService - ----- - - -[[remoting-httpinvoker-client]] -==== Linking in the Service at the Client - -Again, linking in the service from the client much resembles the way you would do it -when you use Hessian. By using a proxy, Spring can translate your calls to -HTTP POST requests to the URL that points to the exported service. The following example -shows how to configure this arrangement: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - - ----- - -As mentioned earlier, you can choose what HTTP client you want to use. By default, the -`HttpInvokerProxy` uses the JDK's HTTP functionality, but you can also use the Apache -`HttpComponents` client by setting the `httpInvokerRequestExecutor` property. -The following example shows how to do so: - -[source,xml,indent=0] -[subs="verbatim,quotes"] ----- - - - ----- +Last but not least, EJB has an advantage over RMI, in that it supports standard +role-based authentication and authorization and remote transaction propagation. It is +possible to get RMI invokers or HTTP invokers to support security context propagation as +well, although this is not provided by core Spring. Spring offers only appropriate hooks +for plugging in third-party or custom solutions. @@ -682,8 +736,387 @@ accordingly first. Check the JAX-WS documentation for details on those requireme + +[[remoting-rmi]] +=== RMI (Deprecated) + +WARNING: As of Spring Framework 5.3, RMI support is deprecated and will not be replaced. + +By using Spring's support for RMI, you can transparently expose your services through the +RMI infrastructure. After having this set up, you basically have a configuration similar +to remote EJBs, except for the fact that there is no standard support for security +context propagation or remote transaction propagation. Spring does provide hooks for +such additional invocation context when you use the RMI invoker, so you can, for example, +plug in security frameworks or custom security credentials. + + +[[remoting-rmi-server]] +==== Exporting the Service by Using `RmiServiceExporter` + +Using the `RmiServiceExporter`, we can expose the interface of our AccountService object +as RMI object. The interface can be accessed by using `RmiProxyFactoryBean`, or via +plain RMI in case of a traditional RMI service. The `RmiServiceExporter` explicitly +supports the exposing of any non-RMI services via RMI invokers. + +We first have to set up our service in the Spring container. +The following example shows how to do so: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + +Next, we have to expose our service by using `RmiServiceExporter`. +The following example shows how to do so: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +In the preceding example, we override the port for the RMI registry. Often, your application +server also maintains an RMI registry, and it is wise to not interfere with that one. +Furthermore, the service name is used to bind the service. So, in the preceding example, the +service is bound at `'rmi://HOST:1199/AccountService'`. We use this URL later on to link in +the service at the client side. + +NOTE: The `servicePort` property has been omitted (it defaults to 0). This means that an +anonymous port is used to communicate with the service. + + +[[remoting-rmi-client]] +==== Linking in the Service at the Client + +Our client is a simple object that uses the `AccountService` to manage accounts, +as the following example shows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public class SimpleObject { + + private AccountService accountService; + + public void setAccountService(AccountService accountService) { + this.accountService = accountService; + } + + // additional methods using the accountService + } +---- + +To link in the service on the client, we create a separate Spring container, +to contain the following simple object and the service linking configuration bits: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +That is all we need to do to support the remote account service on the client. Spring +transparently creates an invoker and remotely enables the account service through the +`RmiServiceExporter`. At the client, we link it in by using the `RmiProxyFactoryBean`. + + + +[[remoting-caucho-protocols]] +=== Using Hessian to Remotely Call Services through HTTP (Deprecated) + +WARNING: As of Spring Framework 5.3, Hessian support is deprecated and will not be replaced. + +Hessian offers a binary HTTP-based remoting protocol. It is developed by Caucho, +and you can find more information about Hessian itself at https://www.caucho.com/[]. + + +[[remoting-caucho-protocols-hessian]] +==== Hessian + +Hessian communicates through HTTP and does so by using a custom servlet. By using Spring's +`DispatcherServlet` principles (see <>), we can wire up such a +servlet to expose your services. First, we have to create a new servlet in our application, +as shown in the following excerpt from `web.xml`: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + remoting + org.springframework.web.servlet.DispatcherServlet + 1 + + + + remoting + /remoting/* + +---- + +If you are familiar with Spring's `DispatcherServlet` principles, you probably +know that now you have to create a Spring container configuration resource named +`remoting-servlet.xml` (after the name of your servlet) in the `WEB-INF` directory. +The application context is used in the next section. + +Alternatively, consider the use of Spring's simpler `HttpRequestHandlerServlet`. Doing so +lets you embed the remote exporter definitions in your root application context (by +default, in `WEB-INF/applicationContext.xml`), with individual servlet definitions +pointing to specific exporter beans. In this case, each servlet name needs to match the bean name of +its target exporter. + + +[[remoting-caucho-protocols-hessian-server]] +==== Exposing Your Beans by Using `HessianServiceExporter` + +In the newly created application context called `remoting-servlet.xml`, we create a +`HessianServiceExporter` to export our services, as the following example shows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + +Now we are ready to link in the service at the client. No explicit handler mapping is +specified (to map request URLs onto services), so we use `BeanNameUrlHandlerMapping` +used. Hence, the service is exported at the URL indicated through its bean name +within the containing `DispatcherServlet` instance's mapping (as defined earlier): +`https://HOST:8080/remoting/AccountService`. + +Alternatively, you can create a `HessianServiceExporter` in your root application context (for example, +in `WEB-INF/applicationContext.xml`), as the following example shows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +In the latter case, you should define a corresponding servlet for this exporter in `web.xml`, +with the same end result: The exporter gets mapped to the request path at +`/remoting/AccountService`. Note that the servlet name needs to match the bean name of +the target exporter. The following example shows how to do so: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + accountExporter + org.springframework.web.context.support.HttpRequestHandlerServlet + + + + accountExporter + /remoting/AccountService + +---- + + +[[remoting-caucho-protocols-hessian-client]] +==== Linking in the Service on the Client + +By using the `HessianProxyFactoryBean`, we can link in the service at the client. The same +principles apply as with the RMI example. We create a separate bean factory or +application context and mention the following beans where the `SimpleObject` is by using +the `AccountService` to manage accounts, as the following example shows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + + +---- + + +[[remoting-caucho-protocols-security]] +==== Applying HTTP Basic Authentication to a Service Exposed through Hessian + +One of the advantages of Hessian is that we can easily apply HTTP basic authentication, +because both protocols are HTTP-based. Your normal HTTP server security mechanism can +be applied through using the `web.xml` security features, for example. Usually, +you need not use per-user security credentials here. Rather, you can use shared credentials that you define +at the `HessianProxyFactoryBean` level (similar to a JDBC `DataSource`), as the following example shows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + + + + +---- + +In the preceding example, we explicitly mention the `BeanNameUrlHandlerMapping` and set +an interceptor, to let only administrators and operators call the beans mentioned in +this application context. + +NOTE: The preceding example does not show a flexible kind of security infrastructure. For +more options as far as security is concerned, have a look at the Spring Security project +at https://projects.spring.io/spring-security/. + + + +[[remoting-httpinvoker]] +=== Spring HTTP Invoker (Deprecated) + +WARNING: As of Spring Framework 5.3, HTTP Invoker support is deprecated and will not be replaced. + +As opposed to Hessian, Spring HTTP invokers are both lightweight protocols that use their own slim +serialization mechanisms and use the standard Java serialization +mechanism to expose services through HTTP. This has a huge advantage if your arguments +and return types are complex types that cannot be serialized by using the serialization +mechanisms Hessian uses (see the next section for more considerations when +you choose a remoting technology). + +Under the hood, Spring uses either the standard facilities provided by the JDK or +Apache `HttpComponents` to perform HTTP calls. If you need more +advanced and easier-to-use functionality, use the latter. See +https://hc.apache.org/httpcomponents-client-ga/[hc.apache.org/httpcomponents-client-ga/] +for more information. + +[CAUTION] +==== +Be aware of vulnerabilities due to unsafe Java deserialization: +Manipulated input streams can lead to unwanted code execution on the server +during the deserialization step. As a consequence, do not expose HTTP invoker +endpoints to untrusted clients. Rather, expose them only between your own services. +In general, we strongly recommend using any other message format (such as JSON) instead. + +If you are concerned about security vulnerabilities due to Java serialization, +consider the general-purpose serialization filter mechanism at the core JVM level, +originally developed for JDK 9 but backported to JDK 8, 7 and 6 in the meantime. See +https://blogs.oracle.com/java-platform-group/entry/incoming_filter_serialization_data_a +and https://openjdk.java.net/jeps/290. +==== + + +[[remoting-httpinvoker-server]] +==== Exposing the Service Object + +Setting up the HTTP invoker infrastructure for a service object closely resembles the +way you would do the same by using Hessian. As Hessian support provides +`HessianServiceExporter`, Spring's HttpInvoker support provides +`org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter`. + +To expose the `AccountService` (mentioned earlier) within a Spring Web MVC +`DispatcherServlet`, the following configuration needs to be in place in the +dispatcher's application context, as the following example shows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +Such an exporter definition is exposed through the `DispatcherServlet` instance's standard +mapping facilities, as explained in <>. + +Alternatively, you can create an `HttpInvokerServiceExporter` in your root application context +(for example, in `'WEB-INF/applicationContext.xml'`), as the following example shows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +In addition, you can define a corresponding servlet for this exporter in `web.xml`, with the +servlet name matching the bean name of the target exporter, as the following example shows: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + accountExporter + org.springframework.web.context.support.HttpRequestHandlerServlet + + + + accountExporter + /remoting/AccountService + +---- + + +[[remoting-httpinvoker-client]] +==== Linking in the Service at the Client + +Again, linking in the service from the client much resembles the way you would do it +when you use Hessian. By using a proxy, Spring can translate your calls to +HTTP POST requests to the URL that points to the exported service. The following example +shows how to configure this arrangement: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + + +---- + +As mentioned earlier, you can choose what HTTP client you want to use. By default, the +`HttpInvokerProxy` uses the JDK's HTTP functionality, but you can also use the Apache +`HttpComponents` client by setting the `httpInvokerRequestExecutor` property. +The following example shows how to do so: + +[source,xml,indent=0] +[subs="verbatim,quotes"] +---- + + + +---- + + + [[remoting-jms]] -=== JMS +=== JMS (Deprecated) + +WARNING: As of Spring Framework 5.3, JMS remoting support is deprecated and will not be replaced. You can also expose services transparently by using JMS as the underlying communication protocol. The JMS remoting support in the Spring Framework is pretty basic. It sends @@ -841,424 +1274,6 @@ The following example defines beans that you can inject into other client-side o -[[remoting-amqp]] -=== AMQP -Remoting via AMQP as the underlying protocol is supported in the Spring AMQP project. -For further details please visit the {doc-spring-amqp}/html/#remoting[Spring Remoting] -section of the Spring AMQP reference. - -[[remoting-autodection-remote-interfaces]] -[NOTE] -==== -Auto-detection is not implemented for remote interfaces - -The main reason why auto-detection of implemented interfaces does not occur for remote -interfaces is to avoid opening too many doors to remote callers. The target object might -implement internal callback interfaces, such as `InitializingBean` or `DisposableBean` -which one would not want to expose to callers. - -Offering a proxy with all interfaces implemented by the target usually does not matter -in the local case. However, when you export a remote service, you should expose a specific -service interface, with specific operations intended for remote usage. Besides internal -callback interfaces, the target might implement multiple business interfaces, with only -one of them intended for remote exposure. For these reasons, we require such a -service interface to be specified. - -This is a trade-off between configuration convenience and the risk of accidental -exposure of internal methods. Always specifying a service interface is not too much -effort and puts you on the safe side regarding controlled exposure of specific methods. -==== - - - -[[remoting-considerations]] -=== Considerations when Choosing a Technology - -Each and every technology presented here has its drawbacks. When choosing a technology, -you should carefully consider your needs, the services you expose, and the objects you -send over the wire. - -When using RMI, you cannot access the objects through the HTTP protocol, -unless you tunnel the RMI traffic. RMI is a fairly heavy-weight protocol, in that it -supports full-object serialization, which is important when you use a complex data model -that needs serialization over the wire. However, RMI-JRMP is tied to Java clients. It is -a Java-to-Java remoting solution. - -Spring's HTTP invoker is a good choice if you need HTTP-based remoting but also rely on -Java serialization. It shares the basic infrastructure with RMI invokers but uses -HTTP as transport. Note that HTTP invokers are not limited only to Java-to-Java remoting -but also to Spring on both the client and the server side. (The latter also applies to -Spring's RMI invoker for non-RMI interfaces.) - -Hessian might provide significant value when operating in a heterogeneous environment, -because they explicitly allow for non-Java clients. However, non-Java support is still -limited. Known issues include the serialization of Hibernate objects in combination with -lazily-initialized collections. If you have such a data model, consider using RMI or -HTTP invokers instead of Hessian. - -JMS can be useful for providing clusters of services and letting the JMS broker take -care of load balancing, discovery, and auto-failover. By default, Java serialization is -used for JMS remoting, but the JMS provider could use a different mechanism for -the wire formatting, such as XStream to let servers be implemented in other -technologies. - -Last but not least, EJB has an advantage over RMI, in that it supports standard -role-based authentication and authorization and remote transaction propagation. It is -possible to get RMI invokers or HTTP invokers to support security context propagation as -well, although this is not provided by core Spring. Spring offers only appropriate hooks -for plugging in third-party or custom solutions. - - - -[[rest-client-access]] -=== REST Endpoints - -The Spring Framework provides two choices for making calls to REST endpoints: - -* <>: The original Spring REST client with a synchronous, template -method API. -* <>: a non-blocking, reactive alternative -that supports both synchronous and asynchronous as well as streaming scenarios. - -NOTE: As of 5.0 the `RestTemplate` is in maintenance mode, with only minor requests for -changes and bugs to be accepted going forward. Please, consider using the -<> which offers a more modern API and -supports sync, async, and streaming scenarios. - - -[[rest-resttemplate]] -==== `RestTemplate` - -The `RestTemplate` provides a higher level API over HTTP client libraries. It makes it -easy to invoke REST endpoints in a single line. It exposes the following groups of -overloaded methods: - -[[rest-overview-of-resttemplate-methods-tbl]] -.RestTemplate methods -[cols="1,3"] -|=== -| Method group | Description - -| `getForObject` -| Retrieves a representation via GET. - -| `getForEntity` -| Retrieves a `ResponseEntity` (that is, status, headers, and body) by using GET. - -| `headForHeaders` -| Retrieves all headers for a resource by using HEAD. - -| `postForLocation` -| Creates a new resource by using POST and returns the `Location` header from the response. - -| `postForObject` -| Creates a new resource by using POST and returns the representation from the response. - -| `postForEntity` -| Creates a new resource by using POST and returns the representation from the response. - -| `put` -| Creates or updates a resource by using PUT. - -| `patchForObject` -| Updates a resource by using PATCH and returns the representation from the response. -Note that the JDK `HttpURLConnection` does not support the `PATCH`, but Apache -HttpComponents and others do. - -| `delete` -| Deletes the resources at the specified URI by using DELETE. - -| `optionsForAllow` -| Retrieves allowed HTTP methods for a resource by using ALLOW. - -| `exchange` -| More generalized (and less opinionated) version of the preceding methods that provides extra -flexibility when needed. It accepts a `RequestEntity` (including HTTP method, URL, headers, -and body as input) and returns a `ResponseEntity`. - -These methods allow the use of `ParameterizedTypeReference` instead of `Class` to specify -a response type with generics. - -| `execute` -| The most generalized way to perform a request, with full control over request -preparation and response extraction through callback interfaces. - -|=== - -[[rest-resttemplate-create]] -===== Initialization - -The default constructor uses `java.net.HttpURLConnection` to perform requests. You can -switch to a different HTTP library with an implementation of `ClientHttpRequestFactory`. -There is built-in support for the following: - -* Apache HttpComponents -* Netty -* OkHttp - -For example, to switch to Apache HttpComponents, you can use the following: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory()); ----- - -Each `ClientHttpRequestFactory` exposes configuration options specific to the underlying -HTTP client library -- for example, for credentials, connection pooling, and other details. - -TIP: Note that the `java.net` implementation for HTTP requests can raise an exception when -accessing the status of a response that represents an error (such as 401). If this is an -issue, switch to another HTTP client library. - -[[rest-resttemplate-uri]] -===== URIs - -Many of the `RestTemplate` methods accept a URI template and URI template variables, -either as a `String` variable argument, or as `Map`. - -The following example uses a `String` variable argument: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - String result = restTemplate.getForObject( - "https://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42", "21"); ----- - -The following example uses a `Map`: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - Map vars = Collections.singletonMap("hotel", "42"); - - String result = restTemplate.getForObject( - "https://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars); ----- - -Keep in mind URI templates are automatically encoded, as the following example shows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - restTemplate.getForObject("https://example.com/hotel list", String.class); - - // Results in request to "https://example.com/hotel%20list" ----- - -You can use the `uriTemplateHandler` property of `RestTemplate` to customize how URIs -are encoded. Alternatively, you can prepare a `java.net.URI` and pass it into one of -the `RestTemplate` methods that accepts a `URI`. - -For more details on working with and encoding URIs, see <>. - -[[rest-template-headers]] -===== Headers - -You can use the `exchange()` methods to specify request headers, as the following example shows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - String uriTemplate = "https://example.com/hotels/{hotel}"; - URI uri = UriComponentsBuilder.fromUriString(uriTemplate).build(42); - - RequestEntity requestEntity = RequestEntity.get(uri) - .header(("MyRequestHeader", "MyValue") - .build(); - - ResponseEntity response = template.exchange(requestEntity, String.class); - - String responseHeader = response.getHeaders().getFirst("MyResponseHeader"); - String body = response.getBody(); ----- - -You can obtain response headers through many `RestTemplate` method variants that return -`ResponseEntity`. - -[[rest-template-body]] -===== Body - -Objects passed into and returned from `RestTemplate` methods are converted to and from raw -content with the help of an `HttpMessageConverter`. - -On a POST, an input object is serialized to the request body, as the following example shows: - ----- -URI location = template.postForLocation("https://example.com/people", person); ----- - -You need not explicitly set the Content-Type header of the request. In most cases, -you can find a compatible message converter based on the source `Object` type, and the chosen -message converter sets the content type accordingly. If necessary, you can use the -`exchange` methods to explicitly provide the `Content-Type` request header, and that, in -turn, influences what message converter is selected. - -On a GET, the body of the response is deserialized to an output `Object`, as the following example shows: - ----- -Person person = restTemplate.getForObject("https://example.com/people/{id}", Person.class, 42); ----- - -The `Accept` header of the request does not need to be explicitly set. In most cases, -a compatible message converter can be found based on the expected response type, which -then helps to populate the `Accept` header. If necessary, you can use the `exchange` -methods to provide the `Accept` header explicitly. - -By default, `RestTemplate` registers all built-in -<>, depending on classpath checks that help -to determine what optional conversion libraries are present. You can also set the message -converters to use explicitly. - -[[rest-message-conversion]] -===== Message Conversion -[.small]#<># - -The `spring-web` module contains the `HttpMessageConverter` contract for reading and -writing the body of HTTP requests and responses through `InputStream` and `OutputStream`. -`HttpMessageConverter` instances are used on the client side (for example, in the `RestTemplate`) and -on the server side (for example, in Spring MVC REST controllers). - -Concrete implementations for the main media (MIME) types are provided in the framework -and are, by default, registered with the `RestTemplate` on the client side and with -`RequestMethodHandlerAdapter` on the server side (see -<>). - -The implementations of `HttpMessageConverter` are described in the following sections. -For all converters, a default media type is used, but you can override it by setting the -`supportedMediaTypes` bean property. The following table describes each implementation: - -[[rest-message-converters-tbl]] -.HttpMessageConverter Implementations -[cols="1,3"] -|=== -| MessageConverter | Description - -| `StringHttpMessageConverter` -| An `HttpMessageConverter` implementation that can read and write `String` instances from the HTTP -request and response. By default, this converter supports all text media types -(`text/{asterisk}`) and writes with a `Content-Type` of `text/plain`. - -| `FormHttpMessageConverter` -| An `HttpMessageConverter` implementation that can read and write form data from the HTTP -request and response. By default, this converter reads and writes the -`application/x-www-form-urlencoded` media type. Form data is read from and written into a -`MultiValueMap`. The converter can also write (but not read) multipart -data read from a `MultiValueMap`. By default, `multipart/form-data` is -supported. As of Spring Framework 5.2, additional multipart subtypes can be supported for -writing form data. Consult the javadoc for `FormHttpMessageConverter` for further details. - -| `ByteArrayHttpMessageConverter` -| An `HttpMessageConverter` implementation that can read and write byte arrays from the -HTTP request and response. By default, this converter supports all media types (`{asterisk}/{asterisk}`) -and writes with a `Content-Type` of `application/octet-stream`. You can override this -by setting the `supportedMediaTypes` property and overriding `getContentType(byte[])`. - -| `MarshallingHttpMessageConverter` -| An `HttpMessageConverter` implementation that can read and write XML by using Spring's -`Marshaller` and `Unmarshaller` abstractions from the `org.springframework.oxm` package. -This converter requires a `Marshaller` and `Unmarshaller` before it can be used. You can inject these -through constructor or bean properties. By default, this converter supports -`text/xml` and `application/xml`. - -| `MappingJackson2HttpMessageConverter` -| An `HttpMessageConverter` implementation that can read and write JSON by using Jackson's -`ObjectMapper`. You can customize JSON mapping as needed through the use of Jackson's -provided annotations. When you need further control (for cases where custom JSON -serializers/deserializers need to be provided for specific types), you can inject a custom `ObjectMapper` -through the `ObjectMapper` property. By default, this -converter supports `application/json`. - -| `MappingJackson2XmlHttpMessageConverter` -| An `HttpMessageConverter` implementation that can read and write XML by using -https://github.com/FasterXML/jackson-dataformat-xml[Jackson XML] extension's -`XmlMapper`. You can customize XML mapping as needed through the use of JAXB -or Jackson's provided annotations. When you need further control (for cases where custom XML -serializers/deserializers need to be provided for specific types), you can inject a custom `XmlMapper` -through the `ObjectMapper` property. By default, this -converter supports `application/xml`. - -| `SourceHttpMessageConverter` -| An `HttpMessageConverter` implementation that can read and write -`javax.xml.transform.Source` from the HTTP request and response. Only `DOMSource`, -`SAXSource`, and `StreamSource` are supported. By default, this converter supports -`text/xml` and `application/xml`. - -| `BufferedImageHttpMessageConverter` -| An `HttpMessageConverter` implementation that can read and write -`java.awt.image.BufferedImage` from the HTTP request and response. This converter reads -and writes the media type supported by the Java I/O API. - -|=== - -[[rest-template-jsonview]] -===== Jackson JSON Views - -You can specify a https://www.baeldung.com/jackson-json-view-annotation[Jackson JSON View] -to serialize only a subset of the object properties, as the following example shows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - MappingJacksonValue value = new MappingJacksonValue(new User("eric", "7!jd#h23")); - value.setSerializationView(User.WithoutPasswordView.class); - - RequestEntity requestEntity = - RequestEntity.post(new URI("https://example.com/user")).body(value); - - ResponseEntity response = template.exchange(requestEntity, String.class); ----- - -[[rest-template-multipart]] -===== Multipart - -To send multipart data, you need to provide a `MultiValueMap` whose values -may be an `Object` for part content, a `Resource` for a file part, or an `HttpEntity` for -part content with headers. For example: - -[source,java,intent=0] -[subs="verbatim,quotes"] ----- - MultiValueMap parts = new LinkedMultiValueMap<>(); - - parts.add("fieldPart", "fieldValue"); - parts.add("filePart", new FileSystemResource("...logo.png")); - parts.add("jsonPart", new Person("Jason")); - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_XML); - parts.add("xmlPart", new HttpEntity<>(myBean, headers)); ----- - -In most cases, you do not have to specify the `Content-Type` for each part. The content -type is determined automatically based on the `HttpMessageConverter` chosen to serialize -it or, in the case of a `Resource` based on the file extension. If necessary, you can -explicitly provide the `MediaType` with an `HttpEntity` wrapper. - -Once the `MultiValueMap` is ready, you can pass it to the `RestTemplate`, as show below: - -[source,java,intent=0] -[subs="verbatim,quotes"] ----- - MultiValueMap parts = ...; - template.postForObject("https://example.com/upload", parts, Void.class); ----- - -If the `MultiValueMap` contains at least one non-`String` value, the `Content-Type` is set -to `multipart/form-data` by the `FormHttpMessageConverter`. If the `MultiValueMap` has -`String` values the `Content-Type` is defaulted to `application/x-www-form-urlencoded`. -If necessary the `Content-Type` may also be set explicitly. - - -[[rest-async-resttemplate]] -==== Using `AsyncRestTemplate` (Deprecated) - -The `AsyncRestTemplate` is deprecated. For all use cases where you might consider using -`AsyncRestTemplate`, use the <> instead. - - - [[ejb]] == Enterprise JavaBeans (EJB) Integration