| /* |
| * 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 org.apache.servicecomb.core.handler.impl; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.concurrent.CompletableFuture; |
| |
| import org.apache.servicecomb.core.Handler; |
| import org.apache.servicecomb.core.Invocation; |
| import org.apache.servicecomb.core.exception.ExceptionUtils; |
| import org.apache.servicecomb.swagger.engine.SwaggerProducerOperation; |
| import org.apache.servicecomb.swagger.invocation.AsyncResponse; |
| import org.apache.servicecomb.swagger.invocation.Response; |
| import org.apache.servicecomb.swagger.invocation.SwaggerInvocation; |
| import org.apache.servicecomb.swagger.invocation.context.ContextUtils; |
| import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory; |
| import org.apache.servicecomb.swagger.invocation.exception.InvocationException; |
| import org.apache.servicecomb.swagger.invocation.extension.ProducerInvokeExtension; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| public class ProducerOperationHandler implements Handler { |
| private static final Logger LOGGER = LoggerFactory.getLogger(ProducerOperationHandler.class); |
| |
| public static final ProducerOperationHandler INSTANCE = new ProducerOperationHandler(); |
| |
| @Override |
| public void handle(Invocation invocation, AsyncResponse asyncResp) { |
| SwaggerProducerOperation producerOperation = invocation.getOperationMeta().getSwaggerProducerOperation(); |
| if (producerOperation == null) { |
| asyncResp.producerFail( |
| ExceptionUtils.producerOperationNotExist(invocation.getSchemaId(), |
| invocation.getOperationName())); |
| return; |
| } |
| invoke(invocation, producerOperation, asyncResp); |
| } |
| |
| private void invoke(Invocation invocation, SwaggerProducerOperation producerOperation, AsyncResponse asyncResp) { |
| if (CompletableFuture.class.equals(producerOperation.getProducerMethod().getReturnType())) { |
| completableFutureInvoke(invocation, producerOperation, asyncResp); |
| return; |
| } |
| |
| syncInvoke(invocation, producerOperation, asyncResp); |
| } |
| |
| public void completableFutureInvoke(Invocation invocation, SwaggerProducerOperation producerOperation, |
| AsyncResponse asyncResp) { |
| ContextUtils.setInvocationContext(invocation); |
| doCompletableFutureInvoke(invocation, producerOperation, asyncResp); |
| ContextUtils.removeInvocationContext(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public void doCompletableFutureInvoke(Invocation invocation, SwaggerProducerOperation producerOperation, |
| AsyncResponse asyncResp) { |
| try { |
| invocation.onBusinessMethodStart(); |
| |
| Object[] args = invocation.toProducerArguments(); |
| for (ProducerInvokeExtension producerInvokeExtension : producerOperation.getProducerInvokeExtenstionList()) { |
| producerInvokeExtension.beforeMethodInvoke(invocation, producerOperation, args); |
| } |
| |
| Object result = producerOperation.getProducerMethod().invoke(producerOperation.getProducerInstance(), args); |
| invocation.onBusinessMethodFinish(); |
| |
| ((CompletableFuture<Object>) result).whenComplete((realResult, ex) -> { |
| invocation.onBusinessFinish(); |
| if (ex == null) { |
| asyncResp.handle(producerOperation.getResponseMapper().mapResponse(invocation.getStatus(), realResult)); |
| return; |
| } |
| |
| asyncResp.handle(processException(invocation, ex)); |
| }); |
| } catch (Throwable e) { |
| if (shouldPrintErrorLog(e)) { |
| invocation.getTraceIdLogger().error(LOGGER, "unexpected error {}, message={}", |
| invocation.getInvocationQualifiedName(), |
| org.apache.servicecomb.foundation.common.utils.ExceptionUtils.getExceptionMessageWithoutTrace(e)); |
| } |
| invocation.onBusinessMethodFinish(); |
| invocation.onBusinessFinish(); |
| asyncResp.handle(processException(invocation, e)); |
| } |
| } |
| |
| public void syncInvoke(Invocation invocation, SwaggerProducerOperation producerOperation, AsyncResponse asyncResp) { |
| ContextUtils.setInvocationContext(invocation); |
| Response response = doInvoke(invocation, producerOperation); |
| ContextUtils.removeInvocationContext(); |
| asyncResp.handle(response); |
| } |
| |
| public Response doInvoke(Invocation invocation, SwaggerProducerOperation producerOperation) { |
| Response response; |
| try { |
| invocation.onBusinessMethodStart(); |
| |
| Object[] args = invocation.toProducerArguments(); |
| for (ProducerInvokeExtension producerInvokeExtension : producerOperation.getProducerInvokeExtenstionList()) { |
| producerInvokeExtension.beforeMethodInvoke(invocation, producerOperation, args); |
| } |
| |
| Object result = producerOperation.getProducerMethod().invoke(producerOperation.getProducerInstance(), args); |
| response = producerOperation.getResponseMapper().mapResponse(invocation.getStatus(), result); |
| |
| invocation.onBusinessMethodFinish(); |
| invocation.onBusinessFinish(); |
| } catch (Throwable e) { |
| if (shouldPrintErrorLog(e)) { |
| invocation.getTraceIdLogger().error(LOGGER, "unexpected error operation={}, message={}", |
| invocation.getInvocationQualifiedName(), |
| org.apache.servicecomb.foundation.common.utils.ExceptionUtils.getExceptionMessageWithoutTrace(e)); |
| } |
| invocation.onBusinessMethodFinish(); |
| invocation.onBusinessFinish(); |
| response = processException(invocation, e); |
| } |
| return response; |
| } |
| |
| protected boolean shouldPrintErrorLog(Throwable throwable) { |
| if (!(throwable instanceof InvocationTargetException)) { |
| return true; |
| } |
| Throwable targetException = ((InvocationTargetException) throwable).getTargetException(); |
| return !(targetException instanceof InvocationException); |
| } |
| |
| protected Response processException(SwaggerInvocation invocation, Throwable e) { |
| if (e instanceof InvocationTargetException) { |
| e = ((InvocationTargetException) e).getTargetException(); |
| } |
| |
| return ExceptionFactory.convertExceptionToResponse(invocation, e); |
| } |
| } |