/*
* 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:
will not have streaming support, even if client code invoked it like so:
* void method(Object param1);
*
This behavior can be changed by setting the
* InputStream in = ...;
* service.method(in);
*
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:
In other words, any combination of return type and parameters is acceptable so long as there is only one
* 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);
*
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());
}
}