4 Replies Latest reply: Mar 9, 2010 10:43 AM by 843793 RSS

    How to refer to genericized interface

    843793
      Hi,

      I have the following interface:
      package org.tbiq.gwt.tools.rpcrequest.server;
      
      import org.tbiq.gwt.tools.rpcrequest.browser.RpcRequest;
      import org.tbiq.gwt.tools.rpcrequest.browser.RpcRequestException;
      import org.tbiq.gwt.tools.rpcrequest.browser.RpcRequestService;
      import org.tbiq.gwt.tools.rpcrequest.browser.RpcResponse;
      
      public interface RpcRequestHandler<ReqT extends RpcRequest<ResT>, ResT extends RpcResponse>
      {
      public boolean isCompatibleWith(Class<ReqT> rpcRequestClass);
      
      public ResT execute(ReqT rpcRequest)
      throws RpcRequestException;
      }
      I also have a dummy implementation of this interface:
      package org.tbiq.gwt.tools.rpcrequest.server;
      
      import org.tbiq.gwt.tools.rpcrequest.browser.DummyRpcRequest;
      import org.tbiq.gwt.tools.rpcrequest.browser.DummyRpcResponse;
      import org.tbiq.gwt.tools.rpcrequest.browser.RpcRequestException;
      
      public class NewDummyRequestHandler
      implements RpcRequestHandler<DummyRpcRequest, DummyRpcResponse>
      {
      @Override
      public DummyRpcResponse execute(DummyRpcRequest rpcRequest)
      throws RpcRequestException
      {
      // TODO Auto-generated method stub
      return null;
      }
      
      @Override
      public boolean isCompatibleWith(Class<DummyRpcRequest> rpcRequestClass)
      {
      if (DummyRpcRequest.class == rpcRequestClass)
      {
      return true;
      }
      return false;
      }
      }
      This interface refers to 2 dummy objects DummyRpcRequest and DummyRpcResponse. There is nothing special about them. They are just regular beans that implement marker interfaces (RpcResponse and RpcRequest<T extends RpcResponse>).
      DummyRpcResponse:
      package org.tbiq.gwt.tools.rpcrequest.browser;
      
      @SuppressWarnings("serial")
      public class DummyRpcResponse
      implements RpcResponse
      {
      }
      DummyRpcRequest:
      package org.tbiq.gwt.tools.rpcrequest.browser;
      
      @SuppressWarnings("serial")
      public class DummyRpcRequest
      implements RpcRequest<DummyRpcResponse>
      {
      }
      Somewhere else, I have a class that implements some other interface. Part of implementing that interface is this method:
      @Override
      public <T extends RpcResponse> T execute(RpcRequest<T> rpcRequest)
      throws RpcRequestException
      {
      RpcRequestHandler<??????> handler = new NewDummyRequestHandler();
      
      return handler.execute(rpcRequest);
      }
      So, the '?????' is my question. How do I refer to the handler such that it compiles. Right now, now matter what I try in that line, the handler.execute(rpcRequest) doesn't compile.

      Also, it's possible that I messed up my RpcRequestHandler interface and defined it in a wrong way (as far as generics are concerned). I am not sure.

      Any help would be much appreciated!

      Thanks,
      Yaakov.

      P.S. The code in the last method is obviously for testing only. I am planning to have a Map of those handlers and choose the handler dynamically based on the type of the RpcRequest that is passed into the execute method.

      Edited by: ychaikin on Feb 23, 2010 1:10 PM
        • 1. Re: How to refer to genericized interface
          843793
          Couple things:

          To match the RPCRequestHandler interface:
          RpcRequestHandler<ReqT extends RpcRequest<ResT>, ResT extends RpcResponse>
          are we assuming DummyRpcRequest is defined like this:
          public class DummyRpcRequest<X> ...
          where X is a subclass of (or implements, dunno how it works) RpcResponse.

          Anyway ... It's been ages since I've delved into generics, and from memory I get the feeling this might fail, because the type "T" can't actually be inferred, but try this:
               @Override
               public <E extends RpcRequest<T>, T extends RpcResponse> T execute(E rpcRequest)
               throws RpcRequestException
               {
                    RpcRequestHandler<E, T> handler = new NewDummyRequestHandler<E, T>();
                    return handler.execute(rpcRequest);
               }
          • 2. Re: How to refer to genericized interface
            843793
            Had a play round some more with this to refresh my knowledge, and understand exactly where you're coming from

            I don't know what your RpcRequest and RpcResponse interfaces look like - although since your concrete implementations DummyRpcRequest and DummyRpcResponse don't implement any methods, I guess that means that the two interfaces are blank.

            The fact that the RpcRequest takes a parameter of a subclass of RpcResponse, though, implies that there's some sort of relationship there. Perhaps, in future, you intend to have a method sig in RpcRequest that say, returns a subclass of (the type of RpcResponse you created the concrete implementation of RpcRequest with). It's hard to offer more suggestions without knowing exactly what you intend with this code.

            A handler takes a RpcRequest<RpcResponse>, runs its execute method, and somehow (depending on implementation) returns an RpcResponse.

            So I tested some code which I guess summarises your situation, and which works okay - if you want, you can blat this all into a file Test.java and compile/run it in textpad.
            interface Response {
                 String message();
            }
            
            class SpecificResponse implements Response {
                 public String message() { return "Why hello there!"; }
            }
            
            interface Request<E extends Response> {}
            
            /* This Request subclass stores a canned, fixed Response object. */
            class StoredResponseRequest<E extends Response> implements Request<E> {
                 private E myResponse;
            
                 public StoredResponseRequest(E useThis) {
                      myResponse = useThis;
                 }
            
                  public E getStoredResponse() {
                      return myResponse;
                 }
            }
            
            /* A handler <B, A> is able to take in a B (extends Request<A>), and return an A. */
            interface Handler<B extends Request<A>, A extends Response> {
                 public A execute(B request);
            }
            
            /* A HandlerForStoredResponseRequests works by assuming that all the Request<A>s it gets passed are, in fact,
                 StoredResponseRequest<A>s. It therefore extracts the necessary A from the object and returns it.  */
            class HandlerForStoredResponseRequests <B extends Request<A>, A extends Response> implements Handler<B, A> {
                 public A execute(B sreq) {
                      return ((StoredResponseRequest<A>)sreq).getStoredResponse();
                 }
            }
            
            
            class Test {
                 public static void main(String[] argz) {
                      Request<Response> request = new StoredResponseRequest<Response>(new SpecificResponse());
                      System.out.println( execute(request).message() );
            
                 }
            
                 public static <T extends Request<E>, E extends Response> E execute(T request) {
                      Handler<T, E> stuffHandler = new HandlerForStoredResponseRequests<T, E>();
                      return stuffHandler.execute(request);
                 }
            }
            • 3. Re: How to refer to genericized interface
              843793
              ychaikin wrote:
              @Override
              public <T extends RpcResponse> T execute(RpcRequest<T> rpcRequest)
              throws RpcRequestException
              {
              RpcRequestHandler<??????> handler = new NewDummyRequestHandler();
              
              return handler.execute(rpcRequest);
              }
              So, the '?????' is my question. How do I refer to the handler such that it compiles. Right now, now matter what I try in that line, the handler.execute(rpcRequest) doesn't compile.
              The long and the short of it is that handler is a handler for (and thus execute only accepts subtypes of) DummyRpcRequests yet rpcRequest may be any kind of RpcRequest. One or the other has to change.

              With kind regards
              Ben
              • 4. Re: How to refer to genericized interface
                843793
                Here is what I ended up with:
                public <RpcRequestT extends RpcRequest<RpcResponseT>, RpcResponseT extends RpcResponse> RpcResponseT execute(RpcRequestT rpcRequest)
                    throws RpcServiceException
                  {
                    // Retrieve RPC request handler for this RPC request
                    RpcRequestHandler<RpcRequestT, RpcResponseT> handler = (RpcRequestHandler<RpcRequestT, RpcResponseT>) rpcRequestHandlerRegistry
                      .getHandlerFor(rpcRequest.getClass());
                where getHandler signature is like this:
                public RpcRequestHandler<? extends RpcRequest<? extends RpcResponse>, ? extends RpcResponse> getHandlerFor(Class<?> rpcRequestClassType);
                Thanks for all the suggestions though.

                Yaakov.