[jboss-remoting-commits] JBoss Remoting SVN: r5557 - remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3.

jboss-remoting-commits at lists.jboss.org jboss-remoting-commits at lists.jboss.org
Fri Oct 16 16:52:24 EDT 2009


Author: david.lloyd at jboss.com
Date: 2009-10-16 16:52:24 -0400 (Fri, 16 Oct 2009)
New Revision: 5557

Added:
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/TypedRequest.java
Modified:
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Client.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientImpl.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/FutureReplyImpl.java
Log:
Additional type-safe request API for clients

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Client.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Client.java	2009-10-09 20:35:17 UTC (rev 5556)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Client.java	2009-10-16 20:52:24 UTC (rev 5557)
@@ -94,6 +94,32 @@
     O invoke(I request) throws IOException, CancellationException;
 
     /**
+     * Send a reqest and block until a reply is received, requiring the reply to be of a specific type.
+     * Otherwise this method functions identically to {@link #invoke(Object) invoke(I)}.
+     *
+     * @param request the reqest to send
+     * @param expectedResultType the expected result type
+     * @return the result of the request
+     * @throws IOException if an I/O error occurred while sending the request
+     * @throws CancellationException if the operation was cancelled asynchronously
+     * @see #invoke(Object) invoke(I)
+     */
+    <T extends O> T invoke(I request, Class<T> expectedResultType) throws IOException, CancellationException;
+
+    /**
+     * Send a typed request and block until a reply is received.  If, for some reason, the given typed request object
+     * is not a subtype of {@link #<I>}, a {@code ClassCastException} is thrown.  Otherwise this method functions
+     * identically to {@link #invoke(Object) invoke(I)}.
+     *
+     * @param request the request
+     * @param <T> the specific reply subtype
+     * @return the result of the request
+     * @throws IOException if an I/O error occurred while sending the request
+     * @throws CancellationException if the operation was cancelled asynchronously
+     */
+    <T extends O> T invoke(TypedRequest<? extends I, T> request) throws IOException, CancellationException, ClassCastException;
+
+    /**
      * Send a request asynchronously.  If the remote side manipulates a stream, it
      * may use a local policy to assign one or more thread(s) to handle the local end of that stream, or it may
      * fail with an exception (e.g. if this method is called on a client with no threads to handle streaming).
@@ -112,4 +138,32 @@
      * @throws IOException if some other I/O error occurred while sending the request
      */
     IoFuture<? extends O> send(I request) throws IOException;
+
+    /**
+     * Send a request asynchronously, requiring the reply to be of a specific result type.
+     * Otherwise this method functions identically to {@link #send(Object) send(I)}.
+     *
+     * @param request the request to send
+     * @param expectedResultType the expected result type class
+     * @param <T> the expected result type
+     * @return a future representing the result of the request
+     * @throws ObjectStreamException if marshalling some part of the request failed
+     * @throws IOException if some other I/O error occurred while sending the request
+     * @see #send(Object) send(I)
+     */
+    <T extends O> IoFuture<? extends T> send(I request, Class<T> expectedResultType) throws IOException;
+
+    /**
+     * Send a typed request asynchronously.  If, for some reason, the given typed request object
+     * is not a subtype of {@link #<I>}, a {@code ClassCastException} is thrown.  Otherwise
+     * this method functions identically to {@link #send(Object) send(I)}.
+     *
+     * @param request the request to send
+     * @param <T> the expected result type
+     * @return a future representing the result of the request
+     * @throws ObjectStreamException if marshalling some part of the request failed
+     * @throws IOException if some other I/O error occurred while sending the request
+     * @see #send(Object) send(I)
+     */
+    <T extends O> IoFuture<? extends T> send(TypedRequest<? extends I, T> request) throws IOException;
 }

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientImpl.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientImpl.java	2009-10-09 20:35:17 UTC (rev 5556)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientImpl.java	2009-10-16 20:52:24 UTC (rev 5557)
@@ -24,6 +24,7 @@
 
 import java.io.IOException;
 import java.util.concurrent.Executor;
+import java.util.concurrent.CancellationException;
 import org.jboss.remoting3.spi.RemoteRequestContext;
 import org.jboss.remoting3.spi.ReplyHandler;
 import org.jboss.remoting3.spi.RequestHandler;
@@ -65,45 +66,61 @@
     }
 
     public O invoke(final I request) throws IOException {
-        if (! isOpen()) {
-            throw new IOException("Client is not open");
-        }
-        log.trace("Client.invoke() sending request \"%s\"", request);
-        final I actualRequest = castRequest(request);
-        final QueueExecutor executor = new QueueExecutor();
-        final FutureReplyImpl<O> futureReply = new FutureReplyImpl<O>(executor, replyClass);
-        final ReplyHandler replyHandler = futureReply.getReplyHandler();
-        final RemoteRequestContext requestContext = handler.receiveRequest(actualRequest, replyHandler);
-        futureReply.setRemoteRequestContext(requestContext);
-        futureReply.addNotifier(IoUtils.attachmentClosingNotifier(), executor);
-        executor.runQueue();
-        try {
-            final O reply = futureReply.getInterruptibly();
-            log.trace("Client.invoke() received reply \"%s\"", reply);
-            return reply;
-        } catch (InterruptedException e) {
-            try {
-                futureReply.cancel();
-                throw new IndeterminateOutcomeException("The current thread was interrupted before the result could be read");
-            } finally {
-                Thread.currentThread().interrupt();
-            }
-        }
+        return invoke(request, replyClass);
     }
 
+    public <T extends O> T invoke(final I request, final Class<T> replyClass) throws IOException, CancellationException {
+       if (! isOpen()) {
+           throw new IOException("Client is not open");
+       }
+       log.trace("Client.invoke() sending request \"%s\"", request);
+       final I actualRequest = castRequest(request);
+       final QueueExecutor executor = new QueueExecutor();
+       final FutureReplyImpl<T> futureReply = new FutureReplyImpl<T>(executor, replyClass);
+       final ReplyHandler replyHandler = futureReply.getReplyHandler();
+       final RemoteRequestContext requestContext = handler.receiveRequest(actualRequest, replyHandler);
+       futureReply.setRemoteRequestContext(requestContext);
+       futureReply.addNotifier(IoUtils.attachmentClosingNotifier(), executor);
+       executor.runQueue();
+       try {
+           final T reply = futureReply.getInterruptibly();
+           log.trace("Client.invoke() received reply \"%s\"", reply);
+           return reply;
+       } catch (InterruptedException e) {
+           try {
+               futureReply.cancel();
+               throw new IndeterminateOutcomeException("The current thread was interrupted before the result could be read");
+           } finally {
+               Thread.currentThread().interrupt();
+           }
+       }
+    }
+
+    public <T extends O> T invoke(final TypedRequest<? extends I, T> typedRequest) throws IOException, CancellationException {
+        return invoke(requestClass.cast(typedRequest), typedRequest.getReplyType());
+    }
+
     public IoFuture<? extends O> send(final I request) throws IOException {
+        return send(request, replyClass);
+    }
+
+    public <T extends O> IoFuture<? extends T> send(final I request, final Class<T> replyClass) throws IOException {
         if (! isOpen()) {
             throw new IOException("Client is not open");
         }
         log.trace("Client.send() sending request \"%s\"", request);
         final I actualRequest = castRequest(request);
-        final FutureReplyImpl<O> futureReply = new FutureReplyImpl<O>(getExecutor(), replyClass);
+        final FutureReplyImpl<T> futureReply = new FutureReplyImpl<T>(getExecutor(), replyClass);
         final ReplyHandler replyHandler = futureReply.getReplyHandler();
         final RemoteRequestContext requestContext = handler.receiveRequest(actualRequest, replyHandler);
         futureReply.setRemoteRequestContext(requestContext);
         return futureReply;
     }
 
+    public <T extends O> IoFuture<? extends T> send(final TypedRequest<? extends I, T> typedRequest) throws IOException {
+        return send(requestClass.cast(typedRequest), typedRequest.getReplyType());
+    }
+
     /**
      * Since type is erased, it's possible that the wrong type was passed.
      * @param request

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/FutureReplyImpl.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/FutureReplyImpl.java	2009-10-09 20:35:17 UTC (rev 5556)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/FutureReplyImpl.java	2009-10-16 20:52:24 UTC (rev 5557)
@@ -35,11 +35,11 @@
 final class FutureReplyImpl<O> extends AbstractIoFuture<O> {
 
     private final Executor executor;
-    private final Class<O> replyType;
+    private final Class<? extends O> replyType;
     private final ReplyHandler replyHandler = new Handler();
     private volatile RemoteRequestContext remoteRequestContext;
 
-    FutureReplyImpl(final Executor executor, final Class<O> replyType) {
+    FutureReplyImpl(final Executor executor, final Class<? extends O> replyType) {
         this.executor = executor;
         this.replyType = replyType;
     }
@@ -65,7 +65,7 @@
     private final class Handler implements ReplyHandler {
 
         public void handleReply(final Object reply) {
-            final Class<O> replyType = FutureReplyImpl.this.replyType;
+            final Class<? extends O> replyType = FutureReplyImpl.this.replyType;
             final O actualReply;
             try {
                 actualReply = replyType.cast(reply);

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/TypedRequest.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/TypedRequest.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/TypedRequest.java	2009-10-16 20:52:24 UTC (rev 5557)
@@ -0,0 +1,41 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3;
+
+/**
+ * A request whose replies should be of a specific type.  Request classes may choose to implement this interface
+ * in order to provide additional type checking and convenience to Remoting API users by causing the reply type
+ * to be chosen based upon the request type.
+ *
+ * @param <I> the request type
+ * @param <O> the reply type for this request type
+ */
+public interface TypedRequest<I extends TypedRequest<I, O>, O> {
+
+    /**
+     * Get the reply type for this request type.
+     *
+     * @return the reply type's class
+     */
+    Class<O> getReplyType();
+}



More information about the jboss-remoting-commits mailing list