001/*
002 * Copyright 2002-2018 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
022import org.springframework.lang.Nullable;
023
024/**
025 * Encapsulates a remote invocation result, holding a result value or an exception.
026 * Used for HTTP-based serialization invokers.
027 *
028 * <p>This is an SPI class, typically not used directly by applications.
029 * Can be subclassed for additional invocation parameters.
030 *
031 * <p>Both {@link RemoteInvocation} and {@link RemoteInvocationResult} are designed
032 * for use with standard Java serialization as well as JavaBean-style serialization.
033 *
034 * @author Juergen Hoeller
035 * @since 1.1
036 * @see RemoteInvocation
037 */
038public class RemoteInvocationResult implements Serializable {
039
040        /** Use serialVersionUID from Spring 1.1 for interoperability. */
041        private static final long serialVersionUID = 2138555143707773549L;
042
043
044        @Nullable
045        private Object value;
046
047        @Nullable
048        private Throwable exception;
049
050
051        /**
052         * Create a new RemoteInvocationResult for the given result value.
053         * @param value the result value returned by a successful invocation
054         * of the target method
055         */
056        public RemoteInvocationResult(@Nullable Object value) {
057                this.value = value;
058        }
059
060        /**
061         * Create a new RemoteInvocationResult for the given exception.
062         * @param exception the exception thrown by an unsuccessful invocation
063         * of the target method
064         */
065        public RemoteInvocationResult(@Nullable Throwable exception) {
066                this.exception = exception;
067        }
068
069        /**
070         * Create a new RemoteInvocationResult for JavaBean-style deserialization
071         * (e.g. with Jackson).
072         * @see #setValue
073         * @see #setException
074         */
075        public RemoteInvocationResult() {
076        }
077
078
079        /**
080         * Set the result value returned by a successful invocation of the
081         * target method, if any.
082         * <p>This setter is intended for JavaBean-style deserialization.
083         * Use {@link #RemoteInvocationResult(Object)} otherwise.
084         * @see #RemoteInvocationResult()
085         */
086        public void setValue(@Nullable Object value) {
087                this.value = value;
088        }
089
090        /**
091         * Return the result value returned by a successful invocation
092         * of the target method, if any.
093         * @see #hasException
094         */
095        @Nullable
096        public Object getValue() {
097                return this.value;
098        }
099
100        /**
101         * Set the exception thrown by an unsuccessful invocation of the
102         * target method, if any.
103         * <p>This setter is intended for JavaBean-style deserialization.
104         * Use {@link #RemoteInvocationResult(Throwable)} otherwise.
105         * @see #RemoteInvocationResult()
106         */
107        public void setException(@Nullable Throwable exception) {
108                this.exception = exception;
109        }
110
111        /**
112         * Return the exception thrown by an unsuccessful invocation
113         * of the target method, if any.
114         * @see #hasException
115         */
116        @Nullable
117        public Throwable getException() {
118                return this.exception;
119        }
120
121        /**
122         * Return whether this invocation result holds an exception.
123         * If this returns {@code false}, the result value applies
124         * (even if it is {@code null}).
125         * @see #getValue
126         * @see #getException
127         */
128        public boolean hasException() {
129                return (this.exception != null);
130        }
131
132        /**
133         * Return whether this invocation result holds an InvocationTargetException,
134         * thrown by an invocation of the target method itself.
135         * @see #hasException()
136         */
137        public boolean hasInvocationTargetException() {
138                return (this.exception instanceof InvocationTargetException);
139        }
140
141
142        /**
143         * Recreate the invocation result, either returning the result value
144         * in case of a successful invocation of the target method, or
145         * rethrowing the exception thrown by the target method.
146         * @return the result value, if any
147         * @throws Throwable the exception, if any
148         */
149        @Nullable
150        public Object recreate() throws Throwable {
151                if (this.exception != null) {
152                        Throwable exToThrow = this.exception;
153                        if (this.exception instanceof InvocationTargetException) {
154                                exToThrow = ((InvocationTargetException) this.exception).getTargetException();
155                        }
156                        RemoteInvocationUtils.fillInClientStackTraceIfPossible(exToThrow);
157                        throw exToThrow;
158                }
159                else {
160                        return this.value;
161                }
162        }
163
164}