/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 com.alipay.remoting.rpc; import org.slf4j.Logger; import com.alipay.remoting.ResponseStatus; import com.alipay.remoting.exception.CodecException; import com.alipay.remoting.exception.ConnectionClosedException; import com.alipay.remoting.exception.DeserializationException; import com.alipay.remoting.exception.RemotingException; import com.alipay.remoting.exception.SerializationException; import com.alipay.remoting.log.BoltLoggerFactory; import com.alipay.remoting.rpc.exception.InvokeException; import com.alipay.remoting.rpc.exception.InvokeSendFailedException; import com.alipay.remoting.rpc.exception.InvokeServerBusyException; import com.alipay.remoting.rpc.exception.InvokeServerException; import com.alipay.remoting.rpc.exception.InvokeTimeoutException; import com.alipay.remoting.rpc.protocol.RpcResponseCommand; import com.alipay.remoting.util.StringUtils; /** * Resolve response object from response command. * * @author jiangping * @version $Id: RpcResponseResolver.java, v 0.1 2015-10-8 PM2:47:29 tao Exp $ */ public class RpcResponseResolver { private static final Logger logger = BoltLoggerFactory.getLogger("RpcRemoting"); /** * Analyze the response command and generate the response object. * * @param responseCommand response command * @param addr response address * @return response object */ public static Object resolveResponseObject(ResponseCommand responseCommand, String addr) throws RemotingException { preProcess(responseCommand, addr); if (responseCommand.getResponseStatus() == ResponseStatus.SUCCESS) { return toResponseObject(responseCommand); } else { String msg = String.format("Rpc invocation exception: %s, the address is %s, id=%s", responseCommand.getResponseStatus(), addr, responseCommand.getId()); logger.warn(msg); if (responseCommand.getCause() != null) { throw new InvokeException(msg, responseCommand.getCause()); } else { throw new InvokeException(msg + ", please check the server log for more."); } } } private static void preProcess(ResponseCommand responseCommand, String addr) throws RemotingException { RemotingException e = null; String msg = null; if (responseCommand == null) { msg = String.format("Rpc invocation timeout[responseCommand null]! the address is %s", addr); e = new InvokeTimeoutException(msg); } else { switch (responseCommand.getResponseStatus()) { case TIMEOUT: msg = String.format( "Rpc invocation timeout[responseCommand TIMEOUT]! the address is %s", addr); e = new InvokeTimeoutException(msg); break; case CLIENT_SEND_ERROR: msg = String.format("Rpc invocation send failed! the address is %s", addr); e = new InvokeSendFailedException(msg, responseCommand.getCause()); break; case CONNECTION_CLOSED: msg = String.format("Connection closed! the address is %s", addr); e = new ConnectionClosedException(msg); break; case SERVER_THREADPOOL_BUSY: msg = String.format("Server thread pool busy! the address is %s, id=%s", addr, responseCommand.getId()); e = new InvokeServerBusyException(msg); break; case CODEC_EXCEPTION: msg = String.format("Codec exception! the address is %s, id=%s", addr, responseCommand.getId()); e = new CodecException(msg); break; case SERVER_SERIAL_EXCEPTION: msg = String .format( "Server serialize response exception! the address is %s, id=%s, serverSide=true", addr, responseCommand.getId()); e = new SerializationException(detailErrMsg(msg, responseCommand), toThrowable(responseCommand), true); break; case SERVER_DESERIAL_EXCEPTION: msg = String .format( "Server deserialize request exception! the address is %s, id=%s, serverSide=true", addr, responseCommand.getId()); e = new DeserializationException(detailErrMsg(msg, responseCommand), toThrowable(responseCommand), true); break; case SERVER_EXCEPTION: msg = String.format( "Server exception! Please check the server log, the address is %s, id=%s", addr, responseCommand.getId()); e = new InvokeServerException(detailErrMsg(msg, responseCommand), toThrowable(responseCommand)); break; default: break; } } if (StringUtils.isNotBlank(msg)) { logger.warn(msg); } if (null != e) { throw e; } } /** * Convert remoting response command to application response object. */ private static Object toResponseObject(ResponseCommand responseCommand) throws CodecException { RpcResponseCommand response = (RpcResponseCommand) responseCommand; response.deserialize(); return response.getResponseObject(); } /** * Convert remoting response command to throwable if it is a throwable, otherwise return null. */ private static Throwable toThrowable(ResponseCommand responseCommand) throws CodecException { RpcResponseCommand resp = (RpcResponseCommand) responseCommand; resp.deserialize(); Object ex = resp.getResponseObject(); if (ex instanceof Throwable) { return (Throwable) ex; } return null; } /** * Detail your error msg with the error msg returned from response command */ private static String detailErrMsg(String clientErrMsg, ResponseCommand responseCommand) { RpcResponseCommand resp = (RpcResponseCommand) responseCommand; if (StringUtils.isNotBlank(resp.getErrorMsg())) { return String.format("%s, ServerErrorMsg:%s", clientErrMsg, resp.getErrorMsg()); } else { return String.format("%s, ServerErrorMsg:null", clientErrMsg); } } }