/* * Copyright 2002-2005 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 * * http://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 com.marathon.util.spring; import org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean; import org.springframework.remoting.httpinvoker.HttpInvokerRequestExecutor; /** * Extends HttpInvokerProxyFactoryBean to allow InputStream parameters to remote service methods and * InputStream return values from remote service methods. Stream content will be not be buffered and will be transmitted using the * "chunked" transfer encoding available in the HTTP protocol, allowing any amount of data to be streamed to or from the service without * worrying about OutOfMemoryErrors (provided your servlet container supports chunked encoding and does not attempt to fully buffer * streams). If a service method has no InputStream parameters or return values then the invocation will proceed in exactly the same fashion as the * standard HttpInvoker (the invocation will actually be delegated to the underlying CommonsHttpInvoker implementation). By default the system will * determine if a service method should be invoked with streaming support based on the signature of the method in the service interface, not on the * actual parameters passed into a particular invocation. For example, this method:
 * void method(Object param1);
 * 
will not have streaming support, even if client code invoked it like so:
 * InputStream in = ...;
 * service.method(in);
 * 
This behavior can be changed by setting the matchOnMethodSignature property of the * StreamSupportingRemoteInvocationFactory contained within the remoteInvocationFactory property of this proxy factory bean * to false. Note that setting this property to false is an experimental feature and may not function properly. *

* WARNING: this is a simplistic implementation and so supports only one InputStream parameter to a service method. For example, these method * signatures are valid and supported:

 * void method1(InputStream param1);
 * void method2(SomeSerializableType param1, InputStream param2);
 * MyType method3(InputStream param1, SomeSerializableType param2, ...);
 * InputStream method4(SomeType param1);
 * InputStream method5(InputStream param1);
 * InputStream method6(InputStream param1, SomeType param2);
 * 
In other words, any combination of return type and parameters is acceptable so long as there is only one InputStream * parameter. This method signature would throw an exception upon invocation:
 * void method7(InputStream param1, InputStream param2);
 * 
*

* Also note that this implementation keeps track of whether the service method explicitly closes the InputStream on the server side and then mirrors * that behavior on the client side. In other words, if the service method closes the InputStream parameter, then the InputStream that the client code * passed into the method on the client side will be closed as well, otherwise the client side InputStream will still be "open" when the service * invocation returns. *

* Finally, configuration of this proxy factory bean is exactly the same as for HttpInvokerProxyFactoryBean, except, of course, you would * reference the StreamSupportingHttpInvokerProxyFactoryBean in your Spring <bean ...> declaration on the client side, and * StreamSupportingHttpInvokerServiceExporter on the server side. Your service code can use the passed in InputStream * parameter just as if it were any other local (in-VM) InputStream. It can also create and return any InputStream, just as if it were a * local invocation. The one exception is that the InputStream passed into the service method will be a standard InputStream implementation. If client * code passed in some custom InputStream implementation with additional methods, then the server will not see that customized implementation or the * additional methods. The only thing the service method will see is the raw bytes that came from the stream. The same applies going back the other * way as well (the return value from the service method). * * @author Andy DePue * @since 1.2.3 * @see StreamSupportingRemoteInvocationFactory#setMatchOnMethodSignature(boolean) * @see StreamSupportingHttpInvokerServiceExporter * @see HttpInvokerProxyFactoryBean * @see org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor * @see org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter * @see java.io.InputStream */ public class StreamSupportingHttpInvokerProxyFactoryBean extends HttpInvokerProxyFactoryBean { public StreamSupportingHttpInvokerProxyFactoryBean(HttpInvokerRequestExecutor executor) { setHttpInvokerRequestExecutor(executor); setRemoteInvocationFactory(new StreamSupportingRemoteInvocationFactory()); } public StreamSupportingHttpInvokerProxyFactoryBean() { setHttpInvokerRequestExecutor(new StreamSupportingHttpInvokerRequestExecutor()); setRemoteInvocationFactory(new StreamSupportingRemoteInvocationFactory()); } }