Archived

This forum has been archived. Please start a new discussion on GitHub.

How to reuse Request in DispatchInterceptor?

ENV
ICE: 3.7.1
JDK: 10.0
WINDOWS 10

My case:
Node_A will send a request to Node_B,then the Node_B will handle the request locally, and it will forward the request to Node_C.
Here is my code sample:

public class ForwardInterceptor extends DispatchInterceptor {
    @Override
    public CompletionStage<OutputStream> dispatch(Request request) throws UserException{


        Identity identity = request.getCurrent().id;
        String serviceName = request.getCurrent().id.name;
        String operation = request.getCurrent().operation;
        Map<String, String> context = request.getCurrent().ctx;

        //get all dest node ids
        List<String> destNodeIdList = JSON.parseArray(context.get("DestNodeId"));



        Object servant = NodeContext.findServant(identity);
        if (servant != null) {
            if(destNodeList.size()<=1){
                //just only dispatch the request to local servant
                return servant.ice_dispatch(request);

            }else{

                //step 1: dispatch the request to local servant
                servant.ice_dispatch(request);              

                //step 2:remove current node Id from destNodeIdList

                //step 3: forward the request to other-nodes
                for(String destNodeId : destNodeIdList){
                    Session destSession = SessionManager.getSession(destNodeId);
                    ObjectPrx base = destSession.getProxy(serviceName);

                    //Error, How to retrieve byte[] inParams from request object?
                    byte[] inParams = getInParams(request); 
                    base.ice_invoke(operation, com.zeroc.Ice.OperationMode.Normal, inParams, context);  

              }
            }
        }
    }


    private byte[] getInParams(Request request){
      Incoming in = (Incoming)request;
      byte[] inParams = in.readParamEncaps();
      in.startOver();
      return inParams;
    }
}

Comments

  • bglmmz
    edited May 2018

    the exception on Node_B:

        at com.zeroc.IceInternal.OutgoingAsyncBaseI.waitForResponse(OutgoingAsyncBaseI.java:92) ~[ice-3.7.1.jar:?]
        at com.zeroc.IceInternal.ProxyIceInvoke.waitForResponse(ProxyIceInvoke.java:73) ~[ice-3.7.1.jar:?]
        at com.zeroc.Ice._ObjectPrxI.ice_invoke(_ObjectPrxI.java:145) ~[ice-3.7.1.jar:?]
    

    the exception on Node_C:

      com.zeroc.Ice.UnmarshalOutOfBoundsException
         reason = ""
        at com.zeroc.Ice.InputStream.readInt(InputStream.java:1299)
        at com.zeroc.Ice.InputStream.readEncapsulation(InputStream.java:686)
        at com.zeroc.IceInternal.Incoming.readParamEncaps(Incoming.java:437)
    
  • benoit
    benoit Rennes, France

    Hi,

    You're using un-documented IceInternal APIs here. You can't use dispatch interceptors for your use case. Instead of dispatch interceptors, you should use the Blobjects API:

    • implement a blobject servant and install it as a default servant (like you did for the dispatch interceptor)
    • the implementation of this blobject servant will forward the request to a number of proxies which can point to a local Ice object from Node_B and a remote Ice object on Node_C.

    On Node_B, you can create an object adapter without endpoints to host the Ice objects that the blobject will invoke on.

    Let us know if you need additional information on this.

    Cheers,
    Benoit.

  • I resolved this problem, and I still used dispatch interceptor.

    ...
      ((Incoming)request).startOver();
      to do something with request;
      ((Incoming)request).startOver();
      ...
      ObjectPrx.ice_invoke(operation, OperationMode.Normal, ((Incoming)request).readParamEncaps(), context);