/*
 * Copyright 2002-2018 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 org.springframework.remoting.support;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.aopalliance.intercept.MethodInvocation;

import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;

Encapsulates a remote invocation, providing core method invocation properties in a serializable fashion. Used for RMI and HTTP-based serialization invokers.

This is an SPI class, typically not used directly by applications. Can be subclassed for additional invocation parameters.

Both RemoteInvocation and RemoteInvocationResult are designed for use with standard Java serialization as well as JavaBean-style serialization.

Author:Juergen Hoeller
See Also:
Since:25.02.2004
/** * Encapsulates a remote invocation, providing core method invocation properties * in a serializable fashion. Used for RMI and HTTP-based serialization invokers. * * <p>This is an SPI class, typically not used directly by applications. * Can be subclassed for additional invocation parameters. * * <p>Both {@link RemoteInvocation} and {@link RemoteInvocationResult} are designed * for use with standard Java serialization as well as JavaBean-style serialization. * * @author Juergen Hoeller * @since 25.02.2004 * @see RemoteInvocationResult * @see RemoteInvocationFactory * @see RemoteInvocationExecutor * @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 {
use serialVersionUID from Spring 1.1 for interoperability.
/** use serialVersionUID from Spring 1.1 for interoperability. */
private static final long serialVersionUID = 6876024250231820554L; private String methodName; private Class<?>[] parameterTypes; private Object[] arguments; private Map<String, Serializable> attributes;
Create a new RemoteInvocation for the given AOP method invocation.
Params:
  • methodInvocation – the AOP invocation to convert
/** * Create a new RemoteInvocation for the given AOP method invocation. * @param methodInvocation the AOP invocation to convert */
public RemoteInvocation(MethodInvocation methodInvocation) { this.methodName = methodInvocation.getMethod().getName(); this.parameterTypes = methodInvocation.getMethod().getParameterTypes(); this.arguments = methodInvocation.getArguments(); }
Create a new RemoteInvocation for the given parameters.
Params:
  • methodName – the name of the method to invoke
  • parameterTypes – the parameter types of the method
  • arguments – the arguments for the invocation
/** * Create a new RemoteInvocation for the given parameters. * @param methodName the name of the method to invoke * @param parameterTypes the parameter types of the method * @param arguments the arguments for the invocation */
public RemoteInvocation(String methodName, Class<?>[] parameterTypes, Object[] arguments) { this.methodName = methodName; this.parameterTypes = parameterTypes; this.arguments = arguments; }
Create a new RemoteInvocation for JavaBean-style deserialization (e.g. with Jackson).
/** * Create a new RemoteInvocation for JavaBean-style deserialization * (e.g. with Jackson). */
public RemoteInvocation() { }
Set the name of the target method.

This setter is intended for JavaBean-style deserialization.

/** * Set the name of the target method. * <p>This setter is intended for JavaBean-style deserialization. */
public void setMethodName(String methodName) { this.methodName = methodName; }
Return the name of the target method.
/** * Return the name of the target method. */
public String getMethodName() { return this.methodName; }
Set the parameter types of the target method.

This setter is intended for JavaBean-style deserialization.

/** * Set the parameter types of the target method. * <p>This setter is intended for JavaBean-style deserialization. */
public void setParameterTypes(Class<?>[] parameterTypes) { this.parameterTypes = parameterTypes; }
Return the parameter types of the target method.
/** * Return the parameter types of the target method. */
public Class<?>[] getParameterTypes() { return this.parameterTypes; }
Set the arguments for the target method call.

This setter is intended for JavaBean-style deserialization.

/** * Set the arguments for the target method call. * <p>This setter is intended for JavaBean-style deserialization. */
public void setArguments(Object[] arguments) { this.arguments = arguments; }
Return the arguments for the target method call.
/** * Return the arguments for the target method call. */
public Object[] getArguments() { return this.arguments; }
Add an additional invocation attribute. Useful to add additional invocation context without having to subclass RemoteInvocation.

Attribute keys have to be unique, and no overriding of existing attributes is allowed.

The implementation avoids to unnecessarily create the attributes Map, to minimize serialization size.

Params:
  • key – the attribute key
  • value – the attribute value
Throws:
/** * Add an additional invocation attribute. Useful to add additional * invocation context without having to subclass RemoteInvocation. * <p>Attribute keys have to be unique, and no overriding of existing * attributes is allowed. * <p>The implementation avoids to unnecessarily create the attributes * Map, to minimize serialization size. * @param key the attribute key * @param value the attribute value * @throws IllegalStateException if the key is already bound */
public void addAttribute(String key, Serializable value) throws IllegalStateException { if (this.attributes == null) { this.attributes = new HashMap<>(); } if (this.attributes.containsKey(key)) { throw new IllegalStateException("There is already an attribute with key '" + key + "' bound"); } this.attributes.put(key, value); }
Retrieve the attribute for the given key, if any.

The implementation avoids to unnecessarily create the attributes Map, to minimize serialization size.

Params:
  • key – the attribute key
Returns:the attribute value, or null if not defined
/** * Retrieve the attribute for the given key, if any. * <p>The implementation avoids to unnecessarily create the attributes * Map, to minimize serialization size. * @param key the attribute key * @return the attribute value, or {@code null} if not defined */
@Nullable public Serializable getAttribute(String key) { if (this.attributes == null) { return null; } return this.attributes.get(key); }
Set the attributes Map. Only here for special purposes: Preferably, use addAttribute and getAttribute.
Params:
  • attributes – the attributes Map
See Also:
/** * Set the attributes Map. Only here for special purposes: * Preferably, use {@link #addAttribute} and {@link #getAttribute}. * @param attributes the attributes Map * @see #addAttribute * @see #getAttribute */
public void setAttributes(@Nullable Map<String, Serializable> attributes) { this.attributes = attributes; }
Return the attributes Map. Mainly here for debugging purposes: Preferably, use addAttribute and getAttribute.
See Also:
Returns:the attributes Map, or null if none created
/** * Return the attributes Map. Mainly here for debugging purposes: * Preferably, use {@link #addAttribute} and {@link #getAttribute}. * @return the attributes Map, or {@code null} if none created * @see #addAttribute * @see #getAttribute */
@Nullable public Map<String, Serializable> getAttributes() { return this.attributes; }
Perform this invocation on the given target object. Typically called when a RemoteInvocation is received on the server.
Params:
  • targetObject – the target object to apply the invocation to
Throws:
See Also:
Returns:the invocation result
/** * Perform this invocation on the given target object. * Typically called when a RemoteInvocation is received on the server. * @param targetObject the target object to apply the invocation to * @return the invocation result * @throws NoSuchMethodException if the method name could not be resolved * @throws IllegalAccessException if the method could not be accessed * @throws InvocationTargetException if the method invocation resulted in an exception * @see java.lang.reflect.Method#invoke */
public Object invoke(Object targetObject) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Method method = targetObject.getClass().getMethod(this.methodName, this.parameterTypes); return method.invoke(targetObject, this.arguments); } @Override public String toString() { return "RemoteInvocation: method name '" + this.methodName + "'; parameter types " + ClassUtils.classNamesToString(this.parameterTypes); } }