diff --git a/build.gradle b/build.gradle index a0d87c6514ed..1d244c529ce2 100644 --- a/build.gradle +++ b/build.gradle @@ -441,5 +441,12 @@ configure(rootProject) { } } } +} + +tasks.named('build').configure { + finalizedBy('publishToMavenLocal') +} +tasks.named('publish').configure { + dependsOn('build') } diff --git a/gradle/spring-module.gradle b/gradle/spring-module.gradle index 7628127cb5d4..8f1a17aa5084 100644 --- a/gradle/spring-module.gradle +++ b/gradle/spring-module.gradle @@ -95,8 +95,29 @@ publishing { artifact javadocJar } } + + repositories { + maven { + name 'nexus' + url = System.getenv("NEXUS_REPO_URL") ? System.getenv("NEXUS_REPO_URL") : + "https://maven.wso2.org/nexus/content/repositories/releases" + credentials { + username rootProject.hasProperty("nexus_username") ? nexus_username : System.getenv("NEXUS_USERNAME") + password rootProject.hasProperty("nexus_password") ? nexus_password : System.getenv("NEXUS_PASSWORD") + } + allowInsecureProtocol = false + } + } } // Disable publication of test fixture artifacts. components.java.withVariantsFromConfiguration(configurations.testFixturesApiElements) { skip() } components.java.withVariantsFromConfiguration(configurations.testFixturesRuntimeElements) { skip() } + +tasks.named('build').configure { + finalizedBy('publishToMavenLocal') +} + +tasks.named('publish').configure { + dependsOn('build') +} 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 9ee3a6c112bf..741d23d97b6f 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 @@ -64,7 +64,6 @@ * @see java.rmi.Remote * @see java.rmi.RemoteException * @see org.springframework.remoting.caucho.HessianServiceExporter - * @see org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter * @deprecated as of 5.3 (phasing out serialization-based remoting) */ @Deprecated diff --git a/spring-context/src/main/java/org/springframework/remoting/support/RemoteInvocation.java b/spring-context/src/main/java/org/springframework/remoting/support/RemoteInvocation.java index fec43c6bb209..371c4e2918c0 100644 --- a/spring-context/src/main/java/org/springframework/remoting/support/RemoteInvocation.java +++ b/spring-context/src/main/java/org/springframework/remoting/support/RemoteInvocation.java @@ -45,7 +45,6 @@ * @see org.springframework.remoting.rmi.RmiProxyFactoryBean * @see org.springframework.remoting.rmi.RmiServiceExporter * @see org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean - * @see org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter */ public class RemoteInvocation implements Serializable { diff --git a/spring-context/src/main/java/org/springframework/remoting/support/RemoteInvocationExecutor.java b/spring-context/src/main/java/org/springframework/remoting/support/RemoteInvocationExecutor.java index 02d456b3a4be..89ab71d5a84d 100644 --- a/spring-context/src/main/java/org/springframework/remoting/support/RemoteInvocationExecutor.java +++ b/spring-context/src/main/java/org/springframework/remoting/support/RemoteInvocationExecutor.java @@ -21,14 +21,12 @@ /** * Strategy interface for executing a {@link RemoteInvocation} on a target object. * - *
Used by {@link org.springframework.remoting.rmi.RmiServiceExporter} (for RMI invokers) - * and by {@link org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter}. + *
Used by {@link org.springframework.remoting.rmi.RmiServiceExporter} (for RMI invokers). * * @author Juergen Hoeller * @since 1.1 * @see DefaultRemoteInvocationFactory * @see org.springframework.remoting.rmi.RmiServiceExporter#setRemoteInvocationExecutor - * @see org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter#setRemoteInvocationExecutor */ public interface RemoteInvocationExecutor { 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 f25139ccf263..97e9a1513ea4 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 @@ -42,7 +42,6 @@ * @since 13.05.2003 * @see HessianClientInterceptor * @see HessianProxyFactoryBean - * @see org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter * @see org.springframework.remoting.rmi.RmiServiceExporter * @deprecated as of 5.3 (phasing out serialization-based remoting) */ 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 361101475e34..0ae0c5f644fe 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 @@ -66,7 +66,6 @@ * @see #setCodebaseUrl * @see #setRemoteInvocationFactory * @see #setHttpInvokerRequestExecutor - * @see HttpInvokerServiceExporter * @see HttpInvokerProxyFactoryBean * @see java.rmi.server.RMIClassLoader * @deprecated as of 5.3 (phasing out serialization-based remoting) 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 ae483e45ff80..0b2d26df05e7 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 @@ -50,7 +50,6 @@ * @see #setServiceUrl * @see #setCodebaseUrl * @see HttpInvokerClientInterceptor - * @see HttpInvokerServiceExporter * @see org.springframework.remoting.rmi.RmiProxyFactoryBean * @see org.springframework.remoting.caucho.HessianProxyFactoryBean * @deprecated as of 5.3 (phasing out serialization-based remoting) 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 deleted file mode 100644 index dc1a0ac746bf..000000000000 --- a/spring-web/src/main/java/org/springframework/remoting/httpinvoker/HttpInvokerServiceExporter.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright 2002-2020 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.remoting.httpinvoker; - -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.OutputStream; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.remoting.support.RemoteInvocation; -import org.springframework.remoting.support.RemoteInvocationResult; -import org.springframework.web.HttpRequestHandler; -import org.springframework.web.util.NestedServletException; - -/** - * Servlet-API-based HTTP request handler that exports the specified service bean - * as HTTP invoker service endpoint, accessible via an HTTP invoker proxy. - * - *
Deserializes remote invocation objects and serializes remote invocation - * result objects. Uses Java serialization just like RMI, but provides the - * same ease of setup as Caucho's HTTP-based Hessian protocol. - * - *
HTTP invoker is the recommended protocol for Java-to-Java remoting. - * It is more powerful and more extensible than Hessian, at the expense of - * being tied to Java. Nevertheless, it is as easy to set up as Hessian, - * which is its main advantage compared to RMI. - * - *
WARNING: Be aware of vulnerabilities due to unsafe Java deserialization: - * Manipulated input streams could lead to unwanted code execution on the server - * during the deserialization step. As a consequence, do not expose HTTP invoker - * endpoints to untrusted clients but rather just between your own services. - * In general, we strongly recommend any other message format (e.g. JSON) instead. - * - * @author Juergen Hoeller - * @since 1.1 - * @see HttpInvokerClientInterceptor - * @see HttpInvokerProxyFactoryBean - * @see org.springframework.remoting.rmi.RmiServiceExporter - * @see org.springframework.remoting.caucho.HessianServiceExporter - * @deprecated as of 5.3 (phasing out serialization-based remoting) - */ -@Deprecated -public class HttpInvokerServiceExporter extends org.springframework.remoting.rmi.RemoteInvocationSerializingExporter implements HttpRequestHandler { - - /** - * Reads a remote invocation from the request, executes it, - * and writes the remote invocation result to the response. - * @see #readRemoteInvocation(HttpServletRequest) - * @see #invokeAndCreateResult(org.springframework.remoting.support.RemoteInvocation, Object) - * @see #writeRemoteInvocationResult(HttpServletRequest, HttpServletResponse, RemoteInvocationResult) - */ - @Override - public void handleRequest(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - - try { - RemoteInvocation invocation = readRemoteInvocation(request); - RemoteInvocationResult result = invokeAndCreateResult(invocation, getProxy()); - writeRemoteInvocationResult(request, response, result); - } - catch (ClassNotFoundException ex) { - throw new NestedServletException("Class not found during deserialization", ex); - } - } - - /** - * Read a RemoteInvocation from the given HTTP request. - *
Delegates to {@link #readRemoteInvocation(HttpServletRequest, InputStream)} with - * the {@link HttpServletRequest#getInputStream() servlet request's input stream}. - * @param request current HTTP request - * @return the RemoteInvocation object - * @throws IOException in case of I/O failure - * @throws ClassNotFoundException if thrown by deserialization - */ - protected RemoteInvocation readRemoteInvocation(HttpServletRequest request) - throws IOException, ClassNotFoundException { - - return readRemoteInvocation(request, request.getInputStream()); - } - - /** - * Deserialize a RemoteInvocation object from the given InputStream. - *
Gives {@link #decorateInputStream} a chance to decorate the stream - * first (for example, for custom encryption or compression). Creates a - * {@link org.springframework.remoting.rmi.CodebaseAwareObjectInputStream} - * and calls {@link #doReadRemoteInvocation} to actually read the object. - *
Can be overridden for custom serialization of the invocation. - * @param request current HTTP request - * @param is the InputStream to read from - * @return the RemoteInvocation object - * @throws IOException in case of I/O failure - * @throws ClassNotFoundException if thrown during deserialization - */ - protected RemoteInvocation readRemoteInvocation(HttpServletRequest request, InputStream is) - throws IOException, ClassNotFoundException { - - try (ObjectInputStream ois = createObjectInputStream(decorateInputStream(request, is))) { - return doReadRemoteInvocation(ois); - } - } - - /** - * Return the InputStream to use for reading remote invocations, - * potentially decorating the given original InputStream. - *
The default implementation returns the given stream as-is. - * Can be overridden, for example, for custom encryption or compression. - * @param request current HTTP request - * @param is the original InputStream - * @return the potentially decorated InputStream - * @throws IOException in case of I/O failure - */ - protected InputStream decorateInputStream(HttpServletRequest request, InputStream is) throws IOException { - return is; - } - - /** - * Write the given RemoteInvocationResult to the given HTTP response. - * @param request current HTTP request - * @param response current HTTP response - * @param result the RemoteInvocationResult object - * @throws IOException in case of I/O failure - */ - protected void writeRemoteInvocationResult( - HttpServletRequest request, HttpServletResponse response, RemoteInvocationResult result) - throws IOException { - - response.setContentType(getContentType()); - writeRemoteInvocationResult(request, response, result, response.getOutputStream()); - } - - /** - * Serialize the given RemoteInvocation to the given OutputStream. - *
The default implementation gives {@link #decorateOutputStream} a chance - * to decorate the stream first (for example, for custom encryption or compression). - * Creates an {@link java.io.ObjectOutputStream} for the final stream and calls - * {@link #doWriteRemoteInvocationResult} to actually write the object. - *
Can be overridden for custom serialization of the invocation. - * @param request current HTTP request - * @param response current HTTP response - * @param result the RemoteInvocationResult object - * @param os the OutputStream to write to - * @throws IOException in case of I/O failure - * @see #decorateOutputStream - * @see #doWriteRemoteInvocationResult - */ - protected void writeRemoteInvocationResult( - HttpServletRequest request, HttpServletResponse response, RemoteInvocationResult result, OutputStream os) - throws IOException { - - try (ObjectOutputStream oos = - createObjectOutputStream(new FlushGuardedOutputStream(decorateOutputStream(request, response, os)))) { - doWriteRemoteInvocationResult(result, oos); - } - } - - /** - * Return the OutputStream to use for writing remote invocation results, - * potentially decorating the given original OutputStream. - *
The default implementation returns the given stream as-is. - * Can be overridden, for example, for custom encryption or compression. - * @param request current HTTP request - * @param response current HTTP response - * @param os the original OutputStream - * @return the potentially decorated OutputStream - * @throws IOException in case of I/O failure - */ - protected OutputStream decorateOutputStream( - HttpServletRequest request, HttpServletResponse response, OutputStream os) throws IOException { - - return os; - } - - - /** - * Decorate an {@code OutputStream} to guard against {@code flush()} calls, - * which are turned into no-ops. - *
Because {@link ObjectOutputStream#close()} will in fact flush/drain - * the underlying stream twice, this {@link FilterOutputStream} will - * guard against individual flush calls. Multiple flush calls can lead - * to performance issues, since writes aren't gathered as they should be. - * @see SPR-14040 - */ - private static class FlushGuardedOutputStream extends FilterOutputStream { - - public FlushGuardedOutputStream(OutputStream out) { - super(out); - } - - @Override - public void flush() throws IOException { - // Do nothing on flush - } - } - -} 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 5c8e431fbaf2..b4bc68011367 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 @@ -53,7 +53,6 @@ * @since 2.5.1 * @see org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor * @see org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean - * @deprecated as of Spring Framework 5.1, in favor of {@link HttpInvokerServiceExporter} */ @Deprecated @org.springframework.lang.UsesSunHttpServer diff --git a/spring-web/src/main/java/org/springframework/web/HttpRequestHandler.java b/spring-web/src/main/java/org/springframework/web/HttpRequestHandler.java index 187d9dd8c544..5552cadf6634 100644 --- a/spring-web/src/main/java/org/springframework/web/HttpRequestHandler.java +++ b/spring-web/src/main/java/org/springframework/web/HttpRequestHandler.java @@ -50,8 +50,7 @@ * DispatcherServlet, indicating that there will never be a view to render. * *
As of Spring 2.0, Spring's HTTP-based remote exporters, such as - * {@link org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter} - * and {@link org.springframework.remoting.caucho.HessianServiceExporter}, + * {@link org.springframework.remoting.caucho.HessianServiceExporter}, * implement this interface rather than the more extensive Controller interface, * for minimal dependencies on Spring-specific web infrastructure. * @@ -71,7 +70,6 @@ * @see org.springframework.web.servlet.mvc.Controller * @see org.springframework.web.servlet.mvc.LastModified * @see org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter - * @see org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter * @see org.springframework.remoting.caucho.HessianServiceExporter */ @FunctionalInterface diff --git a/spring-web/src/main/java/org/springframework/web/context/support/HttpRequestHandlerServlet.java b/spring-web/src/main/java/org/springframework/web/context/support/HttpRequestHandlerServlet.java index 97be4db90667..8a18fc0e5e2e 100644 --- a/spring-web/src/main/java/org/springframework/web/context/support/HttpRequestHandlerServlet.java +++ b/spring-web/src/main/java/org/springframework/web/context/support/HttpRequestHandlerServlet.java @@ -37,8 +37,7 @@ * HttpRequestHandlerServlet servlet-name as defined in {@code web.xml}. * *
This can for example be used to expose a single Spring remote exporter,
- * such as {@link org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter}
- * or {@link org.springframework.remoting.caucho.HessianServiceExporter},
+ * such as {@link org.springframework.remoting.caucho.HessianServiceExporter},
* per HttpRequestHandlerServlet definition. This is a minimal alternative
* to defining remote exporters as beans in a DispatcherServlet context
* (with advanced mapping and interception facilities being available there).
diff --git a/spring-web/src/test/java/org/springframework/remoting/httpinvoker/HttpInvokerTests.java b/spring-web/src/test/java/org/springframework/remoting/httpinvoker/HttpInvokerTests.java
deleted file mode 100644
index 8a2c697b69d8..000000000000
--- a/spring-web/src/test/java/org/springframework/remoting/httpinvoker/HttpInvokerTests.java
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * Copyright 2002-2021 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.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.remoting.httpinvoker;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.OutputStream;
-import java.io.Serializable;
-import java.lang.reflect.InvocationTargetException;
-import java.util.Arrays;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.GZIPOutputStream;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.aopalliance.intercept.MethodInvocation;
-import org.junit.jupiter.api.Test;
-
-import org.springframework.beans.factory.BeanClassLoaderAware;
-import org.springframework.beans.testfixture.beans.ITestBean;
-import org.springframework.beans.testfixture.beans.TestBean;
-import org.springframework.remoting.RemoteAccessException;
-import org.springframework.remoting.support.DefaultRemoteInvocationExecutor;
-import org.springframework.remoting.support.RemoteInvocation;
-import org.springframework.remoting.support.RemoteInvocationResult;
-import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
-import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
-import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
-
-/**
- * @author Juergen Hoeller
- * @since 09.08.2004
- */
-@SuppressWarnings("deprecation")
-class HttpInvokerTests {
-
- @Test
- void httpInvokerProxyFactoryBeanAndServiceExporter() {
- doTestHttpInvokerProxyFactoryBeanAndServiceExporter(false);
- }
-
- @Test
- void httpInvokerProxyFactoryBeanAndServiceExporterWithExplicitClassLoader() {
- doTestHttpInvokerProxyFactoryBeanAndServiceExporter(true);
- }
-
- private void doTestHttpInvokerProxyFactoryBeanAndServiceExporter(boolean explicitClassLoader) {
- TestBean target = new TestBean("myname", 99);
-
- final HttpInvokerServiceExporter exporter = new HttpInvokerServiceExporter();
- exporter.setServiceInterface(ITestBean.class);
- exporter.setService(target);
- exporter.afterPropertiesSet();
-
- HttpInvokerProxyFactoryBean pfb = new HttpInvokerProxyFactoryBean();
- pfb.setServiceInterface(ITestBean.class);
- pfb.setServiceUrl("https://myurl");
-
- pfb.setHttpInvokerRequestExecutor(new AbstractHttpInvokerRequestExecutor() {
- @Override
- protected RemoteInvocationResult doExecuteRequest(
- HttpInvokerClientConfiguration config, ByteArrayOutputStream baos) throws Exception {
- assertThat(config.getServiceUrl()).isEqualTo("https://myurl");
- MockHttpServletRequest request = new MockHttpServletRequest();
- MockHttpServletResponse response = new MockHttpServletResponse();
- request.setContent(baos.toByteArray());
- exporter.handleRequest(request, response);
- return readRemoteInvocationResult(
- new ByteArrayInputStream(response.getContentAsByteArray()), config.getCodebaseUrl());
- }
- });
- if (explicitClassLoader) {
- ((BeanClassLoaderAware) pfb.getHttpInvokerRequestExecutor()).setBeanClassLoader(getClass().getClassLoader());
- }
-
- pfb.afterPropertiesSet();
- ITestBean proxy = (ITestBean) pfb.getObject();
- assertThat(proxy.getName()).isEqualTo("myname");
- assertThat(proxy.getAge()).isEqualTo(99);
- proxy.setAge(50);
- assertThat(proxy.getAge()).isEqualTo(50);
- proxy.setStringArray(new String[] {"str1", "str2"});
- assertThat(Arrays.equals(new String[] {"str1", "str2"}, proxy.getStringArray())).isTrue();
- proxy.setSomeIntegerArray(new Integer[] {1, 2, 3});
- assertThat(Arrays.equals(new Integer[] {1, 2, 3}, proxy.getSomeIntegerArray())).isTrue();
- proxy.setNestedIntegerArray(new Integer[][] {{1, 2, 3}, {4, 5, 6}});
- Integer[][] integerArray = proxy.getNestedIntegerArray();
- assertThat(Arrays.equals(new Integer[] {1, 2, 3}, integerArray[0])).isTrue();
- assertThat(Arrays.equals(new Integer[] {4, 5, 6}, integerArray[1])).isTrue();
- proxy.setSomeIntArray(new int[] {1, 2, 3});
- assertThat(Arrays.equals(new int[] {1, 2, 3}, proxy.getSomeIntArray())).isTrue();
- proxy.setNestedIntArray(new int[][] {{1, 2, 3}, {4, 5, 6}});
- int[][] intArray = proxy.getNestedIntArray();
- assertThat(Arrays.equals(new int[] {1, 2, 3}, intArray[0])).isTrue();
- assertThat(Arrays.equals(new int[] {4, 5, 6}, intArray[1])).isTrue();
-
- assertThatIllegalStateException().isThrownBy(() ->
- proxy.exceptional(new IllegalStateException()));
- assertThatExceptionOfType(IllegalAccessException.class).isThrownBy(() ->
- proxy.exceptional(new IllegalAccessException()));
- }
-
- @Test
- void httpInvokerProxyFactoryBeanAndServiceExporterWithIOException() throws Exception {
- TestBean target = new TestBean("myname", 99);
-
- final HttpInvokerServiceExporter exporter = new HttpInvokerServiceExporter();
- exporter.setServiceInterface(ITestBean.class);
- exporter.setService(target);
- exporter.afterPropertiesSet();
-
- HttpInvokerProxyFactoryBean pfb = new HttpInvokerProxyFactoryBean();
- pfb.setServiceInterface(ITestBean.class);
- pfb.setServiceUrl("https://myurl");
-
- pfb.setHttpInvokerRequestExecutor((config, invocation) -> { throw new IOException("argh"); });
-
- pfb.afterPropertiesSet();
- ITestBean proxy = (ITestBean) pfb.getObject();
- assertThatExceptionOfType(RemoteAccessException.class)
- .isThrownBy(() -> proxy.setAge(50))
- .withCauseInstanceOf(IOException.class);
- }
-
- @Test
- void httpInvokerProxyFactoryBeanAndServiceExporterWithGzipCompression() {
- TestBean target = new TestBean("myname", 99);
-
- final HttpInvokerServiceExporter exporter = new HttpInvokerServiceExporter() {
- @Override
- protected InputStream decorateInputStream(HttpServletRequest request, InputStream is) throws IOException {
- if ("gzip".equals(request.getHeader("Compression"))) {
- return new GZIPInputStream(is);
- }
- else {
- return is;
- }
- }
- @Override
- protected OutputStream decorateOutputStream(
- HttpServletRequest request, HttpServletResponse response, OutputStream os) throws IOException {
- if ("gzip".equals(request.getHeader("Compression"))) {
- return new GZIPOutputStream(os);
- }
- else {
- return os;
- }
- }
- };
- exporter.setServiceInterface(ITestBean.class);
- exporter.setService(target);
- exporter.afterPropertiesSet();
-
- HttpInvokerProxyFactoryBean pfb = new HttpInvokerProxyFactoryBean();
- pfb.setServiceInterface(ITestBean.class);
- pfb.setServiceUrl("https://myurl");
-
- pfb.setHttpInvokerRequestExecutor(new AbstractHttpInvokerRequestExecutor() {
- @Override
- protected RemoteInvocationResult doExecuteRequest(
- HttpInvokerClientConfiguration config, ByteArrayOutputStream baos)
- throws IOException, ClassNotFoundException {
- assertThat(config.getServiceUrl()).isEqualTo("https://myurl");
- MockHttpServletRequest request = new MockHttpServletRequest();
- request.addHeader("Compression", "gzip");
- MockHttpServletResponse response = new MockHttpServletResponse();
- request.setContent(baos.toByteArray());
- try {
- exporter.handleRequest(request, response);
- }
- catch (ServletException ex) {
- throw new IOException(ex.toString());
- }
- return readRemoteInvocationResult(
- new ByteArrayInputStream(response.getContentAsByteArray()), config.getCodebaseUrl());
- }
- @Override
- protected OutputStream decorateOutputStream(OutputStream os) throws IOException {
- return new GZIPOutputStream(os);
- }
- @Override
- protected InputStream decorateInputStream(InputStream is) throws IOException {
- return new GZIPInputStream(is);
- }
- });
-
- pfb.afterPropertiesSet();
- ITestBean proxy = (ITestBean) pfb.getObject();
- assertThat(proxy.getName()).isEqualTo("myname");
- assertThat(proxy.getAge()).isEqualTo(99);
- proxy.setAge(50);
- assertThat(proxy.getAge()).isEqualTo(50);
-
- assertThatIllegalStateException().isThrownBy(() ->
- proxy.exceptional(new IllegalStateException()));
- assertThatExceptionOfType(IllegalAccessException.class).isThrownBy(() ->
- proxy.exceptional(new IllegalAccessException()));
- }
-
- @Test
- void httpInvokerProxyFactoryBeanAndServiceExporterWithWrappedInvocations() {
- TestBean target = new TestBean("myname", 99);
-
- final HttpInvokerServiceExporter exporter = new HttpInvokerServiceExporter() {
- @Override
- protected RemoteInvocation doReadRemoteInvocation(ObjectInputStream ois)
- throws IOException, ClassNotFoundException {
- Object obj = ois.readObject();
- if (!(obj instanceof TestRemoteInvocationWrapper)) {
- throw new IOException("Deserialized object needs to be assignable to type [" +
- TestRemoteInvocationWrapper.class.getName() + "]: " + obj);
- }
- return ((TestRemoteInvocationWrapper) obj).remoteInvocation;
- }
- @Override
- protected void doWriteRemoteInvocationResult(RemoteInvocationResult result, ObjectOutputStream oos)
- throws IOException {
- oos.writeObject(new TestRemoteInvocationResultWrapper(result));
- }
- };
- exporter.setServiceInterface(ITestBean.class);
- exporter.setService(target);
- exporter.afterPropertiesSet();
-
- HttpInvokerProxyFactoryBean pfb = new HttpInvokerProxyFactoryBean();
- pfb.setServiceInterface(ITestBean.class);
- pfb.setServiceUrl("https://myurl");
-
- pfb.setHttpInvokerRequestExecutor(new AbstractHttpInvokerRequestExecutor() {
- @Override
- protected RemoteInvocationResult doExecuteRequest(
- HttpInvokerClientConfiguration config, ByteArrayOutputStream baos) throws Exception {
- assertThat(config.getServiceUrl()).isEqualTo("https://myurl");
- MockHttpServletRequest request = new MockHttpServletRequest();
- MockHttpServletResponse response = new MockHttpServletResponse();
- request.setContent(baos.toByteArray());
- exporter.handleRequest(request, response);
- return readRemoteInvocationResult(
- new ByteArrayInputStream(response.getContentAsByteArray()), config.getCodebaseUrl());
- }
- @Override
- protected void doWriteRemoteInvocation(RemoteInvocation invocation, ObjectOutputStream oos) throws IOException {
- oos.writeObject(new TestRemoteInvocationWrapper(invocation));
- }
- @Override
- protected RemoteInvocationResult doReadRemoteInvocationResult(ObjectInputStream ois)
- throws IOException, ClassNotFoundException {
- Object obj = ois.readObject();
- if (!(obj instanceof TestRemoteInvocationResultWrapper)) {
- throw new IOException("Deserialized object needs to be assignable to type ["
- + TestRemoteInvocationResultWrapper.class.getName() + "]: " + obj);
- }
- return ((TestRemoteInvocationResultWrapper) obj).remoteInvocationResult;
- }
- });
-
- pfb.afterPropertiesSet();
- ITestBean proxy = (ITestBean) pfb.getObject();
- assertThat(proxy.getName()).isEqualTo("myname");
- assertThat(proxy.getAge()).isEqualTo(99);
- proxy.setAge(50);
- assertThat(proxy.getAge()).isEqualTo(50);
-
- assertThatIllegalStateException().isThrownBy(() ->
- proxy.exceptional(new IllegalStateException()));
- assertThatExceptionOfType(IllegalAccessException.class).isThrownBy(() ->
- proxy.exceptional(new IllegalAccessException()));
- }
-
- @Test
- void httpInvokerProxyFactoryBeanAndServiceExporterWithInvocationAttributes() {
- TestBean target = new TestBean("myname", 99);
-
- final HttpInvokerServiceExporter exporter = new HttpInvokerServiceExporter();
- exporter.setServiceInterface(ITestBean.class);
- exporter.setService(target);
- exporter.setRemoteInvocationExecutor(new DefaultRemoteInvocationExecutor() {
- @Override
- public Object invoke(RemoteInvocation invocation, Object targetObject)
- throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
- assertThat(invocation.getAttributes()).isNotNull();
- assertThat(invocation.getAttributes().size()).isEqualTo(1);
- assertThat(invocation.getAttributes().get("myKey")).isEqualTo("myValue");
- assertThat(invocation.getAttribute("myKey")).isEqualTo("myValue");
- return super.invoke(invocation, targetObject);
- }
- });
- exporter.afterPropertiesSet();
-
- HttpInvokerProxyFactoryBean pfb = new HttpInvokerProxyFactoryBean();
- pfb.setServiceInterface(ITestBean.class);
- pfb.setServiceUrl("https://myurl");
- pfb.setRemoteInvocationFactory(methodInvocation -> {
- RemoteInvocation invocation = new RemoteInvocation(methodInvocation);
- invocation.addAttribute("myKey", "myValue");
- assertThatIllegalStateException().isThrownBy(() ->
- invocation.addAttribute("myKey", "myValue"));
- assertThat(invocation.getAttributes()).isNotNull();
- assertThat(invocation.getAttributes().size()).isEqualTo(1);
- assertThat(invocation.getAttributes().get("myKey")).isEqualTo("myValue");
- assertThat(invocation.getAttribute("myKey")).isEqualTo("myValue");
- return invocation;
- });
-
- pfb.setHttpInvokerRequestExecutor(new AbstractHttpInvokerRequestExecutor() {
- @Override
- protected RemoteInvocationResult doExecuteRequest(
- HttpInvokerClientConfiguration config, ByteArrayOutputStream baos) throws Exception {
- assertThat(config.getServiceUrl()).isEqualTo("https://myurl");
- MockHttpServletRequest request = new MockHttpServletRequest();
- MockHttpServletResponse response = new MockHttpServletResponse();
- request.setContent(baos.toByteArray());
- exporter.handleRequest(request, response);
- return readRemoteInvocationResult(
- new ByteArrayInputStream(response.getContentAsByteArray()), config.getCodebaseUrl());
- }
- });
-
- pfb.afterPropertiesSet();
- ITestBean proxy = (ITestBean) pfb.getObject();
- assertThat(proxy.getName()).isEqualTo("myname");
- assertThat(proxy.getAge()).isEqualTo(99);
- }
-
- @Test
- void httpInvokerProxyFactoryBeanAndServiceExporterWithCustomInvocationObject() {
- TestBean target = new TestBean("myname", 99);
-
- final HttpInvokerServiceExporter exporter = new HttpInvokerServiceExporter();
- exporter.setServiceInterface(ITestBean.class);
- exporter.setService(target);
- exporter.setRemoteInvocationExecutor(new DefaultRemoteInvocationExecutor() {
- @Override
- public Object invoke(RemoteInvocation invocation, Object targetObject)
- throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
- boolean condition = invocation instanceof TestRemoteInvocation;
- assertThat(condition).isTrue();
- assertThat(invocation.getAttributes()).isNull();
- assertThat(invocation.getAttribute("myKey")).isNull();
- return super.invoke(invocation, targetObject);
- }
- });
- exporter.afterPropertiesSet();
-
- HttpInvokerProxyFactoryBean pfb = new HttpInvokerProxyFactoryBean();
- pfb.setServiceInterface(ITestBean.class);
- pfb.setServiceUrl("https://myurl");
- pfb.setRemoteInvocationFactory(methodInvocation -> {
- RemoteInvocation invocation = new TestRemoteInvocation(methodInvocation);
- assertThat(invocation.getAttributes()).isNull();
- assertThat(invocation.getAttribute("myKey")).isNull();
- return invocation;
- });
-
- pfb.setHttpInvokerRequestExecutor(new AbstractHttpInvokerRequestExecutor() {
- @Override
- protected RemoteInvocationResult doExecuteRequest(
- HttpInvokerClientConfiguration config, ByteArrayOutputStream baos) throws Exception {
- assertThat(config.getServiceUrl()).isEqualTo("https://myurl");
- MockHttpServletRequest request = new MockHttpServletRequest();
- MockHttpServletResponse response = new MockHttpServletResponse();
- request.setContent(baos.toByteArray());
- exporter.handleRequest(request, response);
- return readRemoteInvocationResult(
- new ByteArrayInputStream(response.getContentAsByteArray()), config.getCodebaseUrl());
- }
- });
-
- pfb.afterPropertiesSet();
- ITestBean proxy = (ITestBean) pfb.getObject();
- assertThat(proxy.getName()).isEqualTo("myname");
- assertThat(proxy.getAge()).isEqualTo(99);
- }
-
- @Test
- void httpInvokerWithSpecialLocalMethods() {
- String serviceUrl = "https://myurl";
- HttpInvokerProxyFactoryBean pfb = new HttpInvokerProxyFactoryBean();
- pfb.setServiceInterface(ITestBean.class);
- pfb.setServiceUrl(serviceUrl);
-
- pfb.setHttpInvokerRequestExecutor((config, invocation) -> { throw new IOException("argh"); });
-
- pfb.afterPropertiesSet();
- ITestBean proxy = (ITestBean) pfb.getObject();
-
- // shouldn't go through to remote service
- assertThat(proxy.toString().contains("HTTP invoker")).isTrue();
- assertThat(proxy.toString().contains(serviceUrl)).isTrue();
- assertThat(proxy.hashCode()).isEqualTo(proxy.hashCode());
- assertThat(proxy.equals(proxy)).isTrue();
-
- // should go through
- assertThatExceptionOfType(RemoteAccessException.class)
- .isThrownBy(() -> proxy.setAge(50))
- .withCauseInstanceOf(IOException.class);
- }
-
-
- @SuppressWarnings("serial")
- private static class TestRemoteInvocation extends RemoteInvocation {
-
- TestRemoteInvocation(MethodInvocation methodInvocation) {
- super(methodInvocation);
- }
- }
-
-
- @SuppressWarnings("serial")
- private static class TestRemoteInvocationWrapper implements Serializable {
-
- private final RemoteInvocation remoteInvocation;
-
- TestRemoteInvocationWrapper(RemoteInvocation remoteInvocation) {
- this.remoteInvocation = remoteInvocation;
- }
- }
-
-
- @SuppressWarnings("serial")
- private static class TestRemoteInvocationResultWrapper implements Serializable {
-
- private final RemoteInvocationResult remoteInvocationResult;
-
- TestRemoteInvocationResultWrapper(RemoteInvocationResult remoteInvocationResult) {
- this.remoteInvocationResult = remoteInvocationResult;
- }
- }
-
-}
diff --git a/src/docs/asciidoc/integration.adoc b/src/docs/asciidoc/integration.adoc
index a5b0dc3e9fe6..23265140971e 100644
--- a/src/docs/asciidoc/integration.adoc
+++ b/src/docs/asciidoc/integration.adoc
@@ -374,10 +374,6 @@ The following remoting technologies are now deprecated and will not be replaced:
`RmiServiceExporter`, Spring supports both traditional RMI (with `java.rmi.Remote`
interfaces and `java.rmi.RemoteException`) and transparent remoting through RMI
invokers (with any Java interface).
-* <