diff --git a/core/src/main/java/io/grpc/Call.java b/core/src/main/java/io/grpc/Call.java index e3aaa66f50..7e53c3a86e 100644 --- a/core/src/main/java/io/grpc/Call.java +++ b/core/src/main/java/io/grpc/Call.java @@ -31,30 +31,31 @@ package io.grpc; - /** - * Low-level methods for communicating with a remote server during a single RPC. Unlike normal RPCs, - * calls may stream any number of requests and responses, although a single request and single - * response is most common. This API is generally intended for use by stubs, but advanced - * applications may have need for it. + * An instance of a call to to a remote method. A call will send zero or more + * request messages to the server and receive zero or more response messages back. * - *

{@link #start} is required to be the first of any methods called. + *

Instances are created + * by a {@link Channel} and used by stubs to invoke their remote behavior. * - *

Any headers must be sent before any payloads, which must be sent before half closing. + *

More advanced usages may consume this interface directly as opposed to using a stub. Common + * reasons for doing so would be the need to interact with flow-control or when acting as a generic + * proxy for arbitrary operations. + * + *

{@link #start} must be called prior to calling any other methods. * *

No generic method for determining message receipt or providing acknowledgement is provided. * Applications are expected to utilize normal payload messages for such signals, as a response - * natually acknowledges its request. + * naturally acknowledges its request. * *

Methods are guaranteed to be non-blocking. Implementations are not required to be thread-safe. + * + * @param type of message sent one or more times to the server. + * @param type of message received one or more times from the server. */ public abstract class Call { /** - * Callbacks for consuming incoming RPC messages. - * - *

Response headers are guaranteed to arrive before any payloads, which are guaranteed - * to arrive before close. An additional block of headers called 'trailers' can be delivered with - * close. + * Callbacks for receiving metadata, response messages and completion status from the server. * *

Implementations are free to block for extended periods of time. Implementations are not * required to be thread-safe. @@ -65,20 +66,27 @@ public abstract class Call { * The response headers have been received. Headers always precede payloads. * This method is always called, if no headers were received then an empty {@link Metadata} * is passed. + * + * @param headers containing metadata sent by the server at the start of the response. */ public abstract void onHeaders(Metadata.Headers headers); /** - * A response payload has been received. For streaming calls, there may be zero payload - * messages. + * A response payload has been received. May be called zero or more times depending on whether + * the call response is empty, a single message or a stream of messages. + * + * @param payload returned by the server */ public abstract void onPayload(T payload); /** * The Call has been closed. No further sending or receiving can occur. If {@code status} is - * not equal to {@link Status#OK}, then the call failed. An additional block of headers may be - * received at the end of the call from the server. An empty {@link Metadata} object is passed - * if no trailers are received. + * not equal to {@link Status#OK}, then the call failed. An additional block of trailer metadata + * may be received at the end of the call from the server. An empty {@link Metadata} object is + * passed if no trailers are received. + * + * @param status the result of the remote call. + * @param trailers metadata provided at call completion. */ public abstract void onClose(Status status, Metadata.Trailers trailers); } @@ -87,10 +95,9 @@ public abstract class Call { * Start a call, using {@code responseListener} for processing response messages. * * @param responseListener receives response messages - * @param headers which can contain extra information like authentication. + * @param headers which can contain extra call metadata, e.g. authentication credentials. * @throws IllegalStateException if call is already started */ - // TODO(louiscryan): Might be better to put into Channel#newCall, might reduce decoration burden public abstract void start(Listener responseListener, Metadata.Headers headers); /** @@ -117,17 +124,17 @@ public abstract class Call { public abstract void cancel(); /** - * Close call for message sending. Incoming messages are unaffected. + * Close the call for request message sending. Incoming response messages are unaffected. * * @throws IllegalStateException if call is already {@code halfClose()}d or {@link #cancel}ed */ public abstract void halfClose(); /** - * Send a payload message. Payload messages are the primary form of communication associated with - * RPCs. Multiple payload messages may exist for streaming calls. + * Send a request message to the server. May be called zero or more times depending on how many + * messages the server is willing to accept for the operation. * - * @param payload message + * @param payload message to be sent to the server. * @throws IllegalStateException if call is {@link #halfClose}d or explicitly {@link #cancel}ed */ public abstract void sendPayload(RequestT payload); diff --git a/core/src/main/java/io/grpc/Channel.java b/core/src/main/java/io/grpc/Channel.java index 51fb49a96b..dcfc7812a4 100644 --- a/core/src/main/java/io/grpc/Channel.java +++ b/core/src/main/java/io/grpc/Channel.java @@ -34,16 +34,29 @@ package io.grpc; import javax.annotation.concurrent.ThreadSafe; /** - * An abstraction layer between stubs and the transport details for use with outgoing calls. - * Channels are responsible for call initiation and tracking. Channels can be decorated to provide - * cross-cutting behaviors across all operations in a stub. + * A Channel provides an abstraction over the transport layer that is designed to be consumed + * by stub implementations. Channel and its associated types {@link Call} and + * {@link Call.Listener} exchange parsed request and response objects whereas the + * transport layer only works with serialized data. + * + *

Applications can add common cross-cutting behaviors to stubs by decorating Channel + * implementations using {@link ClientInterceptor}. It is expected that most application + * code will not use this interface directly but rather work with stubs that have been bound to a + * Channel that was decorated during application initialization, */ @ThreadSafe public interface Channel { /** - * Create a call to the given service method. + * Create a {@link Call} to the remote operation specified by the given + * {@link MethodDescriptor}. The returned {@link Call} does not trigger any remote + * behavior until {@link Call#start(Call.Listener, Metadata.Headers)} is + * invoked. + * + * @param methodDescriptor describes the name and parameter types of the operation to call. + * @return a {@link Call} bound to the specified method. + * */ - // TODO(ejona86): perform start() as part of new Call creation? - public Call newCall(MethodDescriptor method); + public Call newCall( + MethodDescriptor methodDescriptor); } diff --git a/core/src/main/java/io/grpc/ClientInterceptor.java b/core/src/main/java/io/grpc/ClientInterceptor.java index 1a44a51ab5..a100b47c77 100644 --- a/core/src/main/java/io/grpc/ClientInterceptor.java +++ b/core/src/main/java/io/grpc/ClientInterceptor.java @@ -34,19 +34,30 @@ package io.grpc; import javax.annotation.concurrent.ThreadSafe; /** - * Interface for intercepting outgoing RPCs before it reaches the channel. + * Interface for intercepting outgoing calls before they are dispatched by a {@link Channel}. + * + *

Implementers use this mechanism to add cross-cutting behavior to {@link Channel} and + * stub implementations. Common examples of such behavior include: + *

*/ @ThreadSafe public interface ClientInterceptor { /** - * Intercept a new call. General semantics of {@link Channel#newCall} apply. {@code next} may only - * be called once. Returned {@link Call} must not be null. + * Intercept {@link Call} creation by the {@code next} {@link Channel}. + *

+ * Many variations of interception are possible. Complex implementations may return a wrapper + * around the result of {@code next.newCall()}, whereas a simpler implementation may just modify + * the header metadata prior to returning the result of {@code next.newCall()}. * - *

If the implementation throws an exception, the RPC will not be started. - * - * @param method the method to be called - * @param next next processor in the interceptor chain - * @return the call object for the new RPC + * @param method the remote method to be called. + * @param next the channel which is being intercepted. + * @return the call object for the remote operation, never {@code null}. */ - Call interceptCall(MethodDescriptor method, Channel next); + Call interceptCall( + MethodDescriptor method, + Channel next); } diff --git a/core/src/main/java/io/grpc/ClientInterceptors.java b/core/src/main/java/io/grpc/ClientInterceptors.java index 787c464de4..22e163bc34 100644 --- a/core/src/main/java/io/grpc/ClientInterceptors.java +++ b/core/src/main/java/io/grpc/ClientInterceptors.java @@ -39,7 +39,7 @@ import java.util.Iterator; import java.util.List; /** - * Utility class for {@link ClientInterceptor}s + * Utility methods for working with {@link ClientInterceptor}s */ public class ClientInterceptors { @@ -47,16 +47,24 @@ public class ClientInterceptors { private ClientInterceptors() {} /** - * Create a new {@code Channel} that will call {@code interceptors} before starting an RPC on the + * Create a new {@link Channel} that will call {@code interceptors} before starting a call on the * given channel. + * + * @param channel the underlying channel to intercept. + * @param interceptors array of interceptors to bind to {@code channel}. + * @return a new channel instance with the interceptors applied. */ public static Channel intercept(Channel channel, ClientInterceptor... interceptors) { return intercept(channel, Arrays.asList(interceptors)); } /** - * Create a new {@code Channel} that will call {@code interceptors} before starting an RPC on the + * Create a new {@link Channel} that will call {@code interceptors} before starting a call on the * given channel. + * + * @param channel the underlying channel to intercept. + * @param interceptors a list of interceptors to bind to {@code channel}. + * @return a new channel instance with the interceptors applied. */ public static Channel intercept(Channel channel, List interceptors) { Preconditions.checkNotNull(channel); @@ -142,8 +150,8 @@ public class ClientInterceptors { } /** - * A {@link io.grpc.Call.Listener} which forwards all of its methods to another - * {@link io.grpc.Call.Listener}. + * A {@link Call.Listener} which forwards all of its methods to another + * {@link Call.Listener}. */ public static class ForwardingListener extends Call.Listener { diff --git a/core/src/main/java/io/grpc/DeferredInputStream.java b/core/src/main/java/io/grpc/DeferredInputStream.java index 152bb73ac9..ee1cabb12f 100644 --- a/core/src/main/java/io/grpc/DeferredInputStream.java +++ b/core/src/main/java/io/grpc/DeferredInputStream.java @@ -45,15 +45,16 @@ import javax.annotation.Nullable; public abstract class DeferredInputStream extends InputStream { /** - * Produce the entire contents of this stream to the specified target + * Produce the entire contents of this stream to the specified target. * - * @return number of bytes written + * @param target to write to. + * @return number of bytes written. */ public abstract int flushTo(OutputStream target) throws IOException; /** - * Returns the object that backs the stream. If any bytes have been read from the stream - * then {@code null} is returned. + * Returns the object that backs the stream. If any bytes have been read from the stream + * then {@code null} is returned. */ @Nullable public abstract T getDeferred(); diff --git a/core/src/main/java/io/grpc/HandlerRegistry.java b/core/src/main/java/io/grpc/HandlerRegistry.java index c49d70958b..e57f7eb6f3 100644 --- a/core/src/main/java/io/grpc/HandlerRegistry.java +++ b/core/src/main/java/io/grpc/HandlerRegistry.java @@ -34,14 +34,25 @@ package io.grpc; import javax.annotation.Nullable; import javax.annotation.concurrent.ThreadSafe; -/** Registry of services and their methods for dispatching incoming calls. */ +/** + * Registry of services and their methods used by servers to dispatching incoming calls. + */ @ThreadSafe public abstract class HandlerRegistry { - /** Lookup full method name, starting with '/'. Returns {@code null} if method not found. */ + + /** + * Lookup a {@link Method} by its fully-qualified name. All names are expected to be absolute + * paths that start with '/'. + * + * @param methodName to lookup {@link Method} for. + * @return the resolved method or {@code null} if no method for that name exists. + */ @Nullable public abstract Method lookupMethod(String methodName); - /** A method definition and its parent's service definition. */ + /** + * A method belonging to a service to be exposed to remote callers. + */ public static final class Method { private final ServerServiceDefinition serviceDef; private final ServerMethodDefinition methodDef; diff --git a/core/src/main/java/io/grpc/Marshaller.java b/core/src/main/java/io/grpc/Marshaller.java index 4791f248ed..5adb825560 100644 --- a/core/src/main/java/io/grpc/Marshaller.java +++ b/core/src/main/java/io/grpc/Marshaller.java @@ -34,18 +34,29 @@ package io.grpc; import java.io.InputStream; /** - * An typed abstraction over message serialization. + * A typed abstraction over message parsing and serialization. + * + *

Stub implementations will define implementations of this interface for each of the request and + * response messages provided by a service. + * + * @param type of serializable message */ public interface Marshaller { /** - * Given a message produce an {@link InputStream} for it. + * Given a message, produce an {@link InputStream} for it so that it can be written to the wire. + * + * @param value to serialize. + * @return serialized value as stream of bytes. */ - // TODO(louiscryan): Switch to ByteSource equivalent when ready public InputStream stream(T value); /** - * Given an {@link InputStream} parse it into an instance of the declared type. + * Given an {@link InputStream} parse it into an instance of the declared type so that it can be + * passed to application code. + * + * @param stream of bytes for serialized value + * @return parsed value */ public T parse(InputStream stream); } diff --git a/core/src/main/java/io/grpc/MethodDescriptor.java b/core/src/main/java/io/grpc/MethodDescriptor.java index 8acba1d9f6..6a5fe0e2b1 100644 --- a/core/src/main/java/io/grpc/MethodDescriptor.java +++ b/core/src/main/java/io/grpc/MethodDescriptor.java @@ -39,7 +39,12 @@ import java.util.concurrent.TimeUnit; import javax.annotation.concurrent.Immutable; /** - * Descriptor for a single operation, used by Channel to execute a call. + * Description of a remote method used by {@link Channel} to initiate a call. + * + *

Provides the name of the operation to execute as well as {@link Marshaller} instances + * used to parse and serialize request and response messages. + * + *

Can be constructed manually but will often be generated by stub code generators. */ @Immutable public class MethodDescriptor { @@ -77,35 +82,45 @@ public class MethodDescriptor { } /** - * The fully qualified name of the method + * The fully qualified name of the method. */ public String getName() { return name; } /** - * Timeout for the operation in microseconds + * Timeout for the operation in microseconds. */ public long getTimeout() { return timeoutMicros; } /** - * Parse a response payload from the given {@link InputStream} + * Parse a response payload from the given {@link InputStream}. + * + * @param input stream containing response message to parse. + * @return parsed response message object. */ public ResponseT parseResponse(InputStream input) { return responseMarshaller.parse(input); } /** - * Convert a request message to an {@link InputStream} + * Convert a request message to an {@link InputStream}. + * + * @param requestMessage to serialize using the request {@link io.grpc.Marshaller}. + * @return serialized request message. */ public InputStream streamRequest(RequestT requestMessage) { return requestMarshaller.stream(requestMessage); } /** - * Create a new descriptor with a different timeout + * Create a new descriptor with a different timeout. + * + * @param timeout to set on cloned descriptor. + * @param unit of time for {@code timeout}. + * @return a cloned instance with the specified timeout set. */ public MethodDescriptor withTimeout(long timeout, TimeUnit unit) { return new MethodDescriptor(type, name, unit.toMicros(timeout), diff --git a/core/src/main/java/io/grpc/MethodType.java b/core/src/main/java/io/grpc/MethodType.java index 396c8724a9..6237ddad40 100644 --- a/core/src/main/java/io/grpc/MethodType.java +++ b/core/src/main/java/io/grpc/MethodType.java @@ -35,9 +35,29 @@ package io.grpc; * The call type of a method. */ public enum MethodType { + /** + * One request message followed by one response message. + */ UNARY, + + /** + * Zero or more request messages followed by one response message. + */ CLIENT_STREAMING, + + /** + * One request message followed by zero or more response messages. + */ SERVER_STREAMING, + + /** + * Zero or more request and response messages arbitrarily interleaved in time. + */ DUPLEX_STREAMING, + + /** + * Cardinality and temporal relationships are not known. Implementations should not make + * buffering assumptions and should largely treat the same as {@link #DUPLEX_STREAMING}. + */ UNKNOWN } diff --git a/core/src/main/java/io/grpc/MutableHandlerRegistry.java b/core/src/main/java/io/grpc/MutableHandlerRegistry.java index 9e58e125cd..f078fd516f 100644 --- a/core/src/main/java/io/grpc/MutableHandlerRegistry.java +++ b/core/src/main/java/io/grpc/MutableHandlerRegistry.java @@ -34,7 +34,10 @@ package io.grpc; import javax.annotation.Nullable; import javax.annotation.concurrent.ThreadSafe; -/** Mutable registry of services and their methods for dispatching incoming calls. */ +/** + * Mutable implementation of {@link HandlerRegistry}. Used by server implementations + * that need to bind and unbind services that are exposed to remote clients. + */ @ThreadSafe public abstract class MutableHandlerRegistry extends HandlerRegistry { /** @@ -43,7 +46,9 @@ public abstract class MutableHandlerRegistry extends HandlerRegistry { @Nullable public abstract ServerServiceDefinition addService(ServerServiceDefinition service); - /** Returns {@code false} if {@code service} was not registered. */ + /** + * Returns {@code false} if {@code service} was not registered. + */ @Nullable public abstract boolean removeService(ServerServiceDefinition service); } diff --git a/core/src/main/java/io/grpc/MutableHandlerRegistryImpl.java b/core/src/main/java/io/grpc/MutableHandlerRegistryImpl.java index 6412093fa1..35f53fee83 100644 --- a/core/src/main/java/io/grpc/MutableHandlerRegistryImpl.java +++ b/core/src/main/java/io/grpc/MutableHandlerRegistryImpl.java @@ -37,7 +37,12 @@ import java.util.concurrent.ConcurrentMap; import javax.annotation.Nullable; import javax.annotation.concurrent.ThreadSafe; -/** Mutable registry implementation of services and their methods for dispatching incoming calls. */ +/** + * Default implementation of {@link MutableHandlerRegistry}. + * + *

Uses {@link ConcurrentHashMap} to avoid service registration excessively + * blocking method lookup. + */ @ThreadSafe public final class MutableHandlerRegistryImpl extends MutableHandlerRegistry { private final ConcurrentMap services diff --git a/core/src/main/java/io/grpc/SerializingExecutor.java b/core/src/main/java/io/grpc/SerializingExecutor.java index 9e76b5de99..cca19a987f 100644 --- a/core/src/main/java/io/grpc/SerializingExecutor.java +++ b/core/src/main/java/io/grpc/SerializingExecutor.java @@ -42,13 +42,10 @@ import java.util.logging.Logger; import javax.annotation.concurrent.GuardedBy; /** - * Executor ensuring that all Runnables submitted are executed in order, - * using the provided Executor, and serially such that no two will ever - * be running at the same time. - * - * @author JJ Furman + * Executor ensuring that all {@link Runnable} tasks submitted are executed in order + * using the provided {@link Executor}, and serially such that no two will ever be + * running at the same time. */ - // TODO(madongfly): figure out a way to not expose it or move it to transport package. public final class SerializingExecutor implements Executor { private static final Logger log = diff --git a/core/src/main/java/io/grpc/ServerCall.java b/core/src/main/java/io/grpc/ServerCall.java index fdb682998b..ced1c248a7 100644 --- a/core/src/main/java/io/grpc/ServerCall.java +++ b/core/src/main/java/io/grpc/ServerCall.java @@ -33,10 +33,10 @@ package io.grpc; /** - * Low-level method for communicating with a remote client during a single RPC. Unlike normal RPCs, - * calls may stream any number of requests and responses, although a single request and single - * response is most common. This API is generally intended for use generated handlers, but advanced - * applications may have need for it. + * Encapsulates a single call received from a remote client. Calls may not simply be unary + * request-response even though this is the most common pattern. Calls may stream any number of + * requests and responses. This API is generally intended for use by generated handlers, + * but applications may use it directly if they need to. * *

Headers must be sent before any payloads, which must be sent before closing. * @@ -45,6 +45,8 @@ package io.grpc; * naturally acknowledges its request. * *

Methods are guaranteed to be non-blocking. Implementations are not required to be thread-safe. + * + * @param parsed type of response message. */ public abstract class ServerCall { /** @@ -61,8 +63,10 @@ public abstract class ServerCall { // a case then we either get to generate a half close or purposefully omit it. public abstract static class Listener { /** - * A request payload has been received. For streaming calls, there may be zero payload + * A request message has been received. For streaming calls, there may be zero or more request * messages. + * + * @param payload a received request message. */ public abstract void onPayload(RequestT payload); @@ -74,7 +78,7 @@ public abstract class ServerCall { /** * The call was cancelled and the server is encouraged to abort processing to save resources, * since the client will not process any further messages. Cancellations can be caused by - * timeouts, explicit cancel by client, network errors, and similar. + * timeouts, explicit cancellation by the client, network errors, etc. * *

There will be no further callbacks for the call. */ @@ -91,7 +95,11 @@ public abstract class ServerCall { /** * Requests up to the given number of messages from the call to be delivered to - * {@link Listener#onPayload(Object)}. No additional messages will be delivered. + * {@link Listener#onPayload(Object)}. Once {@code numMessages} have been delivered + * no further request messages will be delivered until more messages are requested by + * calling this method again. + * + *

Servers use this mechanism to provide back-pressure to the client for flow-control. * * @param numMessages the requested number of messages to be delivered to the listener. */ @@ -108,10 +116,10 @@ public abstract class ServerCall { public abstract void sendHeaders(Metadata.Headers headers); /** - * Send a payload message. Payload messages are the primary form of communication associated with - * RPCs. Multiple payload messages may exist for streaming calls. + * Send a response message. Payload messages are the primary form of communication associated with + * RPCs. Multiple response messages may exist for streaming calls. * - * @param payload message + * @param payload response message. * @throws IllegalStateException if call is {@link #close}d */ public abstract void sendPayload(ResponseT payload); diff --git a/core/src/main/java/io/grpc/ServerCallHandler.java b/core/src/main/java/io/grpc/ServerCallHandler.java index ab767cb32d..566c6ec723 100644 --- a/core/src/main/java/io/grpc/ServerCallHandler.java +++ b/core/src/main/java/io/grpc/ServerCallHandler.java @@ -34,11 +34,11 @@ package io.grpc; import javax.annotation.concurrent.ThreadSafe; /** - * Interface to begin processing incoming RPCs. Advanced applications and generated code implement - * this interface to implement service methods. + * Interface to initiate processing of incoming remote calls. Advanced applications and generated + * code will implement this interface to allows {@link Server}s to invoke service methods. */ @ThreadSafe -public interface ServerCallHandler { +public interface ServerCallHandler { /** * Produce a non-{@code null} listener for the incoming call. Implementations are free to call * methods on {@code call} before this method has returned. @@ -47,10 +47,10 @@ public interface ServerCallHandler { * Implementations must not throw an exception if they started processing that may use {@code * call} on another thread. * - * @param fullMethodName full method name of call - * @param call object for responding - * @return listener for processing incoming messages for {@code call} + * @param fullMethodName full qualified method name of call. + * @param call object for responding to the remote client. + * @return listener for processing incoming request messages for {@code call} */ - ServerCall.Listener startCall(String fullMethodName, ServerCall call, + ServerCall.Listener startCall(String fullMethodName, ServerCall call, Metadata.Headers headers); } diff --git a/core/src/main/java/io/grpc/ServerImpl.java b/core/src/main/java/io/grpc/ServerImpl.java index 3bed1360eb..991d3ff1f2 100644 --- a/core/src/main/java/io/grpc/ServerImpl.java +++ b/core/src/main/java/io/grpc/ServerImpl.java @@ -85,7 +85,8 @@ public class ServerImpl implements Server { * Construct a server. {@link #setTransportServer(Service)} must be called before starting the * server. * - * @param executor + * @param executor to call methods on behalf of remote clients + * @param registry of methods to expose to remote clients. */ public ServerImpl(Executor executor, HandlerRegistry registry) { this.executor = Preconditions.checkNotNull(executor); diff --git a/core/src/main/java/io/grpc/ServerInterceptor.java b/core/src/main/java/io/grpc/ServerInterceptor.java index 7f9cb37591..4a3d9cbef5 100644 --- a/core/src/main/java/io/grpc/ServerInterceptor.java +++ b/core/src/main/java/io/grpc/ServerInterceptor.java @@ -34,23 +34,36 @@ package io.grpc; import javax.annotation.concurrent.ThreadSafe; /** - * Interface for intercepting incoming RPCs before the handler receives them. + * Interface for intercepting incoming calls before that are dispatched by + * {@link ServerCallHandler}. + * + *

Implementers use this mechanism to add cross-cutting behavior to server-side calls. Common + * example of such behavior include: + *

*/ @ThreadSafe public interface ServerInterceptor { /** - * Intercept a new call. General semantics of {@link ServerCallHandler#startCall} apply. {@code - * next} may only be called once. Returned listener must not be {@code null}. + * Intercept {@link ServerCall} dispatch by the {@code next} {@link ServerCallHandler}. General + * semantics of {@link ServerCallHandler#startCall} apply and the returned + * {@link io.grpc.ServerCall.Listener} must not be {@code null}. * *

If the implementation throws an exception, {@code call} will be closed with an error. * Implementations must not throw an exception if they started processing that may use {@code * call} on another thread. * - * @param method full method name of the call - * @param call object for responding + * @param method fully qualified method name of the call + * @param call object to receive response messages * @param next next processor in the interceptor chain - * @return listener for processing incoming messages for {@code call} + * @return listener for processing incoming messages for {@code call}, never {@code null}. */ - ServerCall.Listener interceptCall(String method, ServerCall call, - Metadata.Headers headers, ServerCallHandler next); + ServerCall.Listener interceptCall( + String method, + ServerCall call, + Metadata.Headers headers, + ServerCallHandler next); } diff --git a/core/src/main/java/io/grpc/ServerInterceptors.java b/core/src/main/java/io/grpc/ServerInterceptors.java index 13df6e4f5d..c05a47f58c 100644 --- a/core/src/main/java/io/grpc/ServerInterceptors.java +++ b/core/src/main/java/io/grpc/ServerInterceptors.java @@ -38,14 +38,20 @@ import java.util.Arrays; import java.util.Iterator; import java.util.List; -/** Utility class for {@link ServerInterceptor}s. */ +/** + * Utility methods for working with {@link ServerInterceptor}s. + */ public class ServerInterceptors { // Prevent instantiation private ServerInterceptors() {} /** - * Create a new {@code ServerServiceDefinition} whose {@link ServerCallHandler}s will call {@code - * interceptors} before calling the pre-existing {@code ServerCallHandler}. + * Create a new {@code ServerServiceDefinition} whose {@link ServerCallHandler}s will call + * {@code interceptors} before calling the pre-existing {@code ServerCallHandler}. + * + * @param serviceDef the service definition for which to intercept all its methods. + * @param interceptors array of interceptors to apply to the service. + * @return a wrapped version of {@code serviceDef} with the interceptors applied. */ public static ServerServiceDefinition intercept(ServerServiceDefinition serviceDef, ServerInterceptor... interceptors) { @@ -53,8 +59,12 @@ public class ServerInterceptors { } /** - * Create a new {@code ServerServiceDefinition} whose {@link ServerCallHandler}s will call {@code - * interceptors} before calling the pre-existing {@code ServerCallHandler}. + * Create a new {@code ServerServiceDefinition} whose {@link ServerCallHandler}s will call + * {@code interceptors} before calling the pre-existing {@code ServerCallHandler}. + * + * @param serviceDef the service definition for which to intercept all its methods. + * @param interceptors list of interceptors to apply to the service. + * @return a wrapped version of {@code serviceDef} with the interceptors applied. */ public static ServerServiceDefinition intercept(ServerServiceDefinition serviceDef, List interceptors) { diff --git a/core/src/main/java/io/grpc/ServerMethodDefinition.java b/core/src/main/java/io/grpc/ServerMethodDefinition.java index be94639c7b..f4fa45b62e 100644 --- a/core/src/main/java/io/grpc/ServerMethodDefinition.java +++ b/core/src/main/java/io/grpc/ServerMethodDefinition.java @@ -33,7 +33,10 @@ package io.grpc; import java.io.InputStream; -/** Definition of a method supported by a service. */ +/** + * Definition of a method bound by a {@link io.grpc.HandlerRegistry} and exposed + * by a {@link Server}. + */ public final class ServerMethodDefinition { private final String name; private final Marshaller requestMarshaller; @@ -50,6 +53,15 @@ public final class ServerMethodDefinition { this.handler = handler; } + /** + * Create a new instance. + * + * @param name the simple name of a method. + * @param requestMarshaller marshaller for request messages. + * @param responseMarshaller marshaller for response messages. + * @param handler to dispatch calls to. + * @return a new instance. + */ public static ServerMethodDefinition create( String name, Marshaller requestMarshaller, Marshaller responseMarshaller, ServerCallHandler handler) { @@ -62,12 +74,22 @@ public final class ServerMethodDefinition { return name; } - /** Deserialize an incoming request message. */ + /** + * Parse an incoming request message. + * + * @param input the serialized message as a byte stream. + * @return a parsed instance of the message. + */ public RequestT parseRequest(InputStream input) { return requestMarshaller.parse(input); } - /** Serialize an outgoing response message. */ + /** + * Serialize an outgoing response message. + * + * @param response the response message to serialize. + * @return the serialized message as a byte stream. + */ public InputStream streamResponse(ResponseT response) { return responseMarshaller.stream(response); } @@ -77,7 +99,12 @@ public final class ServerMethodDefinition { return handler; } - /** Create a new method definition with a different call handler. */ + /** + * Create a new method definition with a different call handler. + * + * @param handler to bind to a cloned instance of this. + * @return a cloned instance of this with the new handler bound. + */ public ServerMethodDefinition withServerCallHandler( ServerCallHandler handler) { return new ServerMethodDefinition( diff --git a/core/src/main/java/io/grpc/Status.java b/core/src/main/java/io/grpc/Status.java index f1e39d983b..246a20abf3 100644 --- a/core/src/main/java/io/grpc/Status.java +++ b/core/src/main/java/io/grpc/Status.java @@ -43,122 +43,166 @@ import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; /** - * Defines the status of an operation using the canonical error space. + * Defines the status of an operation by providing a standard {@link Code} in conjunction with an + * optional descriptive message. + * + *

For clients, every remote call will return a status on completion. In the case of errors this + * status may be propagated to blocking stubs as a {@link java.lang.RuntimeException} or to + * a listener as an explicit parameter. + * + *

Similarly servers can report a status by throwing {@link OperationRuntimeException} + * or by passing the status to a callback. + * + *

Utility functions are provided to convert a status to an exception and to extract them + * back out. */ @Immutable public final class Status { /** - * The set of canonical error codes. If new codes are added over time they must choose - * a numerical value that does not collide with any previously defined code. + * The set of canonical status codes. If new codes are added over time they must choose + * a numerical value that does not collide with any previously used value. */ public enum Code { + /** + * The operation completed successfully. + */ OK(0), - // The operation was cancelled (typically by the caller). + /** + * The operation was cancelled (typically by the caller). + */ CANCELLED(1), - // Unknown error. An example of where this error may be returned is - // if a Status value received from another address space belongs to - // an error-space that is not known in this address space. Also - // errors raised by APIs that do not return enough error information - // may be converted to this error. + /** + * Unknown error. An example of where this error may be returned is + * if a Status value received from another address space belongs to + * an error-space that is not known in this address space. Also + * errors raised by APIs that do not return enough error information + * may be converted to this error. + */ UNKNOWN(2), - // Client specified an invalid argument. Note that this differs - // from FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments - // that are problematic regardless of the state of the system - // (e.g., a malformed file name). + /** + * Client specified an invalid argument. Note that this differs + * from FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments + * that are problematic regardless of the state of the system + * (e.g., a malformed file name). + */ INVALID_ARGUMENT(3), - // Deadline expired before operation could complete. For operations - // that change the state of the system, this error may be returned - // even if the operation has completed successfully. For example, a - // successful response from a server could have been delayed long - // enough for the deadline to expire. + /** + * Deadline expired before operation could complete. For operations + * that change the state of the system, this error may be returned + * even if the operation has completed successfully. For example, a + * successful response from a server could have been delayed long + * enough for the deadline to expire. + */ DEADLINE_EXCEEDED(4), - // Some requested entity (e.g., file or directory) was not found. + /** + * Some requested entity (e.g., file or directory) was not found. + */ NOT_FOUND(5), - // Some entity that we attempted to create (e.g., file or directory) - // already exists. + /** + * Some entity that we attempted to create (e.g., file or directory) already exists. + */ ALREADY_EXISTS(6), - // The caller does not have permission to execute the specified - // operation. PERMISSION_DENIED must not be used for rejections - // caused by exhausting some resource (use RESOURCE_EXHAUSTED - // instead for those errors). PERMISSION_DENIED must not be - // used if the caller cannot be identified (use UNAUTHENTICATED - // instead for those errors). + /** + * The caller does not have permission to execute the specified + * operation. PERMISSION_DENIED must not be used for rejections + * caused by exhausting some resource (use RESOURCE_EXHAUSTED + * instead for those errors). PERMISSION_DENIED must not be + * used if the caller cannot be identified (use UNAUTHENTICATED + * instead for those errors). + */ PERMISSION_DENIED(7), - // Some resource has been exhausted, perhaps a per-user quota, or - // perhaps the entire file system is out of space. + /** + * Some resource has been exhausted, perhaps a per-user quota, or + * perhaps the entire file system is out of space. + */ RESOURCE_EXHAUSTED(8), - // Operation was rejected because the system is not in a state - // required for the operation's execution. For example, directory - // to be deleted may be non-empty, an rmdir operation is applied to - // a non-directory, etc. - // - // A litmus test that may help a service implementor in deciding - // between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE: - // (a) Use UNAVAILABLE if the client can retry just the failing call. - // (b) Use ABORTED if the client should retry at a higher-level - // (e.g., restarting a read-modify-write sequence). - // (c) Use FAILED_PRECONDITION if the client should not retry until - // the system state has been explicitly fixed. E.g., if an "rmdir" - // fails because the directory is non-empty, FAILED_PRECONDITION - // should be returned since the client should not retry unless - // they have first fixed up the directory by deleting files from it. + /** + * Operation was rejected because the system is not in a state + * required for the operation's execution. For example, directory + * to be deleted may be non-empty, an rmdir operation is applied to + * a non-directory, etc. + * + *

A litmus test that may help a service implementor in deciding + * between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE: + * (a) Use UNAVAILABLE if the client can retry just the failing call. + * (b) Use ABORTED if the client should retry at a higher-level + * (e.g., restarting a read-modify-write sequence). + * (c) Use FAILED_PRECONDITION if the client should not retry until + * the system state has been explicitly fixed. E.g., if an "rmdir" + * fails because the directory is non-empty, FAILED_PRECONDITION + * should be returned since the client should not retry unless + * they have first fixed up the directory by deleting files from it. + */ FAILED_PRECONDITION(9), - // The operation was aborted, typically due to a concurrency issue - // like sequencer check failures, transaction aborts, etc. - // - // See litmus test above for deciding between FAILED_PRECONDITION, - // ABORTED, and UNAVAILABLE. + /** + * The operation was aborted, typically due to a concurrency issue + * like sequencer check failures, transaction aborts, etc. + * + *

See litmus test above for deciding between FAILED_PRECONDITION, + * ABORTED, and UNAVAILABLE. + */ ABORTED(10), - // Operation was attempted past the valid range. E.g., seeking or - // reading past end of file. - // - // Unlike INVALID_ARGUMENT, this error indicates a problem that may - // be fixed if the system state changes. For example, a 32-bit file - // system will generate INVALID_ARGUMENT if asked to read at an - // offset that is not in the range [0,2^32-1], but it will generate - // OUT_OF_RANGE if asked to read from an offset past the current - // file size. - // - // There is a fair bit of overlap between FAILED_PRECONDITION and - // OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific - // error) when it applies so that callers who are iterating through - // a space can easily look for an OUT_OF_RANGE error to detect when - // they are done. + /** + * Operation was attempted past the valid range. E.g., seeking or + * reading past end of file. + * + *

Unlike INVALID_ARGUMENT, this error indicates a problem that may + * be fixed if the system state changes. For example, a 32-bit file + * system will generate INVALID_ARGUMENT if asked to read at an + * offset that is not in the range [0,2^32-1], but it will generate + * OUT_OF_RANGE if asked to read from an offset past the current + * file size. + * + *

There is a fair bit of overlap between FAILED_PRECONDITION and OUT_OF_RANGE. + * We recommend using OUT_OF_RANGE (the more specific error) when it applies + * so that callers who are iterating through + * a space can easily look for an OUT_OF_RANGE error to detect when they are done. + */ OUT_OF_RANGE(11), - // Operation is not implemented or not supported/enabled in this service. + /** + * Operation is not implemented or not supported/enabled in this service. + */ UNIMPLEMENTED(12), - // Internal errors. Means some invariants expected by underlying - // system has been broken. If you see one of these errors, - // something is very broken. + /** + * Internal errors. Means some invariants expected by underlying + * system has been broken. If you see one of these errors, + * something is very broken. + */ INTERNAL(13), - // The service is currently unavailable. This is a most likely a - // transient condition and may be corrected by retrying with - // a backoff. - // - // See litmus test above for deciding between FAILED_PRECONDITION, - // ABORTED, and UNAVAILABLE. + /** + * The service is currently unavailable. This is a most likely a + * transient condition and may be corrected by retrying with + * a backoff. + * + *

See litmus test above for deciding between FAILED_PRECONDITION, + * ABORTED, and UNAVAILABLE. + */ UNAVAILABLE(14), - // Unrecoverable data loss or corruption. + /** + * Unrecoverable data loss or corruption. + */ DATA_LOSS(15), - // The request does not have valid authentication credentials for the - // operation. + /** + * The request does not have valid authentication credentials for the + * operation. + */ UNAUTHENTICATED(16); private final int value; @@ -169,6 +213,9 @@ public final class Status { this.valueAscii = Integer.toString(value); } + /** + * The numerical value of the code. + */ public int value() { return value; } @@ -229,13 +276,13 @@ public final class Status { } /** - * Key to bind status code to trailers. + * Key to bind status code to trailing metadata. */ public static final Metadata.Key CODE_KEY = Metadata.Key.of("grpc-status", new StatusCodeMarshaller()); /** - * Key to bind status message to trailers. + * Key to bind status message to trailing metadata. */ public static final Metadata.Key MESSAGE_KEY = Metadata.Key.of("grpc-message", Metadata.ASCII_STRING_MARSHALLER); @@ -290,7 +337,8 @@ public final class Status { } /** - * Create a derived instance of {@link Status} with the given description. + * Create a derived instance of {@link Status} augmenting the current description with + * additional detail. */ public Status augmentDescription(String additionalDetail) { if (additionalDetail == null) { @@ -302,15 +350,24 @@ public final class Status { } } + /** + * The canonical status code. + */ public Code getCode() { return code; } + /** + * A description of this status for human consumption. + */ @Nullable public String getDescription() { return description; } + /** + * The underlying cause of an error. + */ @Nullable public Throwable getCause() { return cause;