/**
* Copyright (c) 2009 Juwi MacMillan Group GmbH
*
* 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 org.tizzit.util.spring.httpinvoker;
import org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean;
/**
* Extends <code>HttpInvokerProxyFactoryBean</code> to allow
* <code>InputStream</code> parameters to remote service methods and
* <code>InputStream</code> 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 <code>OutOfMemoryErrors</code> (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:
* <code><pre>
* void method(Object param1);
* </pre></code>
* will not have streaming support, even if client code invoked it like so:
* <code><pre>
* InputStream in = ...;
* service.method(in);
* </pre></code>
* This behavior can be changed by setting the
* <code>matchOnMethodSignature</code> property of the
* <code>StreamSupportingRemoteInvocationFactory</code> contained within the
* <code>remoteInvocationFactory</code> property of this proxy factory bean to
* <code>false</code>. Note that setting this property to <code>false</code>
* is an experimental feature and may not function properly.
*
* <p><b>WARNING:</b> 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:
* <code><pre>
* 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);
* </pre></code>
* In other words, any combination of return type and parameters is acceptable
* so long as there is only one <code>InputStream</code> parameter. This
* method signature would throw an exception upon invocation:
* <code><pre>
* void method7(InputStream param1, InputStream param2);
* </pre></code>
* <p>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.
* <p>Finally, configuration of this proxy factory bean is exactly the same
* as for <code>HttpInvokerProxyFactoryBean</code>, except, of course, you
* would reference the <code>StreamSupportingHttpInvokerProxyFactoryBean</code>
* in your Spring <bean ...> declaration on the client side, and
* <code>StreamSupportingHttpInvokerServiceExporter</code> on the server side.
* Your service code can use the passed in <code>InputStream</code> parameter
* just as if it were any other local (in-VM) <code>InputStream</code>. 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()
{
setHttpInvokerRequestExecutor(new StreamSupportingHttpInvokerRequestExecutor());
setRemoteInvocationFactory(new StreamSupportingRemoteInvocationFactory());
}
}