001/*
002 * Copyright 2002-2014 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.remoting.support;
018
019import java.io.Serializable;
020import java.lang.reflect.InvocationTargetException;
021
022/**
023 * Encapsulates a remote invocation result, holding a result value or an exception.
024 * Used for HTTP-based serialization invokers.
025 *
026 * <p>This is an SPI class, typically not used directly by applications.
027 * Can be subclassed for additional invocation parameters.
028 *
029 * <p>Both {@link RemoteInvocation} and {@link RemoteInvocationResult} are designed
030 * for use with standard Java serialization as well as JavaBean-style serialization.
031 *
032 * @author Juergen Hoeller
033 * @since 1.1
034 * @see RemoteInvocation
035 */
036public class RemoteInvocationResult implements Serializable {
037
038        /** Use serialVersionUID from Spring 1.1 for interoperability */
039        private static final long serialVersionUID = 2138555143707773549L;
040
041
042        private Object value;
043
044        private Throwable exception;
045
046
047        /**
048         * Create a new RemoteInvocationResult for the given result value.
049         * @param value the result value returned by a successful invocation
050         * of the target method
051         */
052        public RemoteInvocationResult(Object value) {
053                this.value = value;
054        }
055
056        /**
057         * Create a new RemoteInvocationResult for the given exception.
058         * @param exception the exception thrown by an unsuccessful invocation
059         * of the target method
060         */
061        public RemoteInvocationResult(Throwable exception) {
062                this.exception = exception;
063        }
064
065        /**
066         * Create a new RemoteInvocationResult for JavaBean-style deserialization
067         * (e.g. with Jackson).
068         * @see #setValue
069         * @see #setException
070         */
071        public RemoteInvocationResult() {
072        }
073
074
075        /**
076         * Set the result value returned by a successful invocation of the
077         * target method, if any.
078         * <p>This setter is intended for JavaBean-style deserialization.
079         * Use {@link #RemoteInvocationResult(Object)} otherwise.
080         * @see #RemoteInvocationResult()
081         */
082        public void setValue(Object value) {
083                this.value = value;
084        }
085
086        /**
087         * Return the result value returned by a successful invocation
088         * of the target method, if any.
089         * @see #hasException
090         */
091        public Object getValue() {
092                return this.value;
093        }
094
095        /**
096         * Set the exception thrown by an unsuccessful invocation of the
097         * target method, if any.
098         * <p>This setter is intended for JavaBean-style deserialization.
099         * Use {@link #RemoteInvocationResult(Throwable)} otherwise.
100         * @see #RemoteInvocationResult()
101         */
102        public void setException(Throwable exception) {
103                this.exception = exception;
104        }
105
106        /**
107         * Return the exception thrown by an unsuccessful invocation
108         * of the target method, if any.
109         * @see #hasException
110         */
111        public Throwable getException() {
112                return this.exception;
113        }
114
115        /**
116         * Return whether this invocation result holds an exception.
117         * If this returns {@code false}, the result value applies
118         * (even if it is {@code null}).
119         * @see #getValue
120         * @see #getException
121         */
122        public boolean hasException() {
123                return (this.exception != null);
124        }
125
126        /**
127         * Return whether this invocation result holds an InvocationTargetException,
128         * thrown by an invocation of the target method itself.
129         * @see #hasException()
130         */
131        public boolean hasInvocationTargetException() {
132                return (this.exception instanceof InvocationTargetException);
133        }
134
135
136        /**
137         * Recreate the invocation result, either returning the result value
138         * in case of a successful invocation of the target method, or
139         * rethrowing the exception thrown by the target method.
140         * @return the result value, if any
141         * @throws Throwable the exception, if any
142         */
143        public Object recreate() throws Throwable {
144                if (this.exception != null) {
145                        Throwable exToThrow = this.exception;
146                        if (this.exception instanceof InvocationTargetException) {
147                                exToThrow = ((InvocationTargetException) this.exception).getTargetException();
148                        }
149                        RemoteInvocationUtils.fillInClientStackTraceIfPossible(exToThrow);
150                        throw exToThrow;
151                }
152                else {
153                        return this.value;
154                }
155        }
156
157}