blob: 488a504331e32a95b63df5634babccb68019708e [file] [log] [blame]
/*
* 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);
}
}