/* * Copyright 2014 The gRPC 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 io.grpc.stub; import static com.google.common.base.Preconditions.checkNotNull; import io.grpc.CallCredentials; import io.grpc.CallOptions; import io.grpc.Channel; import io.grpc.ClientInterceptor; import io.grpc.ClientInterceptors; import io.grpc.Deadline; import io.grpc.ExperimentalApi; import io.grpc.ManagedChannelBuilder; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import javax.annotation.CheckReturnValue; import javax.annotation.Nullable; import javax.annotation.concurrent.ThreadSafe; /** * Common base type for stub implementations. Stub configuration is immutable; changing the * configuration returns a new stub with updated configuration. Changing the configuration is cheap * and may be done before every RPC, such as would be common when using {@link #withDeadlineAfter}. * *
Configuration is stored in {@link CallOptions} and is passed to the {@link Channel} when * performing an RPC. * *
DO NOT MOCK: Customizing options doesn't work properly in mocks. Use InProcessChannelBuilder
* to create a real channel suitable for testing. It is also possible to mock Channel instead.
*
* @since 1.0.0
* @param the concrete type of this stub.
*/
@ThreadSafe
@CheckReturnValue
public abstract class AbstractStub> {
private final Channel channel;
private final CallOptions callOptions;
/**
* Constructor for use by subclasses, with the default {@code CallOptions}.
*
* @since 1.0.0
* @param channel the channel that this stub will use to do communications
*/
protected AbstractStub(Channel channel) {
this(channel, CallOptions.DEFAULT);
}
/**
* Constructor for use by subclasses, with the default {@code CallOptions}.
*
* @since 1.0.0
* @param channel the channel that this stub will use to do communications
* @param callOptions the runtime call options to be applied to every call on this stub
*/
protected AbstractStub(Channel channel, CallOptions callOptions) {
this.channel = checkNotNull(channel, "channel");
this.callOptions = checkNotNull(callOptions, "callOptions");
}
/**
* The underlying channel of the stub.
*
* @since 1.0.0
*/
public final Channel getChannel() {
return channel;
}
/**
* The {@code CallOptions} of the stub.
*
* @since 1.0.0
*/
public final CallOptions getCallOptions() {
return callOptions;
}
/**
* Returns a new stub with the given channel for the provided method configurations.
*
* @since 1.0.0
* @param channel the channel that this stub will use to do communications
* @param callOptions the runtime call options to be applied to every call on this stub
*/
protected abstract S build(Channel channel, CallOptions callOptions);
/**
* Returns a new stub with an absolute deadline.
*
*
This is mostly used for propagating an existing deadline. {@link #withDeadlineAfter} is the * recommended way of setting a new deadline, * * @since 1.0.0 * @param deadline the deadline or {@code null} for unsetting the deadline. */ public final S withDeadline(@Nullable Deadline deadline) { return build(channel, callOptions.withDeadline(deadline)); } /** * Returns a new stub with a deadline that is after the given {@code duration} from now. * * @since 1.0.0 * @see CallOptions#withDeadlineAfter */ public final S withDeadlineAfter(long duration, TimeUnit unit) { return build(channel, callOptions.withDeadlineAfter(duration, unit)); } /** * Returns a new stub with the given executor that is to be used instead of the default one * specified with {@link ManagedChannelBuilder#executor}. Note that setting this option may not * take effect for blocking calls. * * @since 1.8.0 */ public final S withExecutor(Executor executor) { return build(channel, callOptions.withExecutor(executor)); } /** * Set's the compressor name to use for the call. It is the responsibility of the application * to make sure the server supports decoding the compressor picked by the client. To be clear, * this is the compressor used by the stub to compress messages to the server. To get * compressed responses from the server, set the appropriate {@link io.grpc.DecompressorRegistry} * on the {@link io.grpc.ManagedChannelBuilder}. * * @since 1.0.0 * @param compressorName the name (e.g. "gzip") of the compressor to use. */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1704") public final S withCompression(String compressorName) { return build(channel, callOptions.withCompression(compressorName)); } /** * Returns a new stub that uses the given channel. * *
This method is vestigial and is unlikely to be useful. Instead, users should prefer to
* use {@link #withInterceptors}.
*
* @since 1.0.0
*/
@Deprecated // use withInterceptors() instead
public final S withChannel(Channel newChannel) {
return build(newChannel, callOptions);
}
/**
* Sets a custom option to be passed to client interceptors on the channel
* {@link io.grpc.ClientInterceptor} via the CallOptions parameter.
*
* @since 1.0.0
* @param key the option being set
* @param value the value for the key
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1869")
public final If unset, the {@link ManagedChannelBuilder#maxInboundMessageSize(int)} limit is used.
*
* @since 1.1.0
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/2563")
public final S withMaxInboundMessageSize(int maxSize) {
return build(channel, callOptions.withMaxInboundMessageSize(maxSize));
}
/**
* Returns a new stub that limits the maximum acceptable message size to send a remote peer.
*
* @since 1.1.0
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/2563")
public final S withMaxOutboundMessageSize(int maxSize) {
return build(channel, callOptions.withMaxOutboundMessageSize(maxSize));
}
}