use of core.framework.api.web.service.Path in project core-ng-project by neowu.
the class WebServiceClientBuilder method buildMethod.
private String buildMethod(Method method) {
CodeBuilder builder = new CodeBuilder();
Type returnType = method.getGenericReturnType();
Map<String, Integer> pathParamIndexes = Maps.newHashMap();
Type requestBeanType = null;
Integer requestBeanIndex = null;
builder.append("public {} {}(", type(returnType), method.getName());
Annotation[][] annotations = method.getParameterAnnotations();
Class<?>[] parameterTypes = method.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
Class<?> paramClass = parameterTypes[i];
if (i > 0)
builder.append(", ");
builder.append("{} param{}", type(paramClass), i);
PathParam pathParam = Params.annotation(annotations[i], PathParam.class);
if (pathParam != null) {
pathParamIndexes.put(pathParam.value(), i);
} else {
requestBeanIndex = i;
requestBeanType = method.getGenericParameterTypes()[i];
}
}
builder.append(") {\n");
builder.indent(1).append("java.lang.reflect.Type requestType = {};\n", requestBeanType == null ? "null" : variable(requestBeanType));
builder.indent(1).append("Object requestBean = {};\n", requestBeanIndex == null ? "null" : "param" + requestBeanIndex);
builder.indent(1).append("java.util.Map pathParams = new java.util.HashMap();\n");
pathParamIndexes.forEach((name, index) -> builder.indent(1).append("pathParams.put({}, param{});\n", variable(name), index));
String returnTypeLiteral = returnType == void.class ? type(Void.class) : type(returnType);
String path = method.getDeclaredAnnotation(Path.class).value();
// to pass path as string literal, the escaped char will not be transferred, like \\, currently not convert is because only type regex may contain special char
builder.indent(1).append("String serviceURL = client.serviceURL({}, pathParams);\n", variable(path));
HTTPMethod httpMethod = HTTPMethods.httpMethod(method);
builder.indent(1).append("{} response = ({}) client.execute({}, serviceURL, requestType, requestBean, {});\n", returnTypeLiteral, returnTypeLiteral, variable(httpMethod), variable(returnType));
if (returnType != void.class)
builder.indent(1).append("return response;\n");
builder.append("}");
return builder.build();
}
use of core.framework.api.web.service.Path in project core-ng-project by neowu.
the class APIConfig method service.
public <T> void service(Class<T> serviceInterface, T service) {
logger.info("create api service, interface={}", serviceInterface.getCanonicalName());
new WebServiceInterfaceValidator(serviceInterface, context.httpServer.handler.requestBeanMapper, context.httpServer.handler.responseBeanTypeValidator).validate();
new WebServiceImplValidator<>(serviceInterface, service).validate();
for (Method method : serviceInterface.getMethods()) {
HTTPMethod httpMethod = HTTPMethods.httpMethod(method);
String path = method.getDeclaredAnnotation(Path.class).value();
Controller controller = new WebServiceControllerBuilder<>(serviceInterface, service, method).build();
try {
Class<?>[] parameterTypes = method.getParameterTypes();
Class<?> serviceClass = service.getClass();
Method targetMethod = serviceClass.getMethod(method.getName(), parameterTypes);
String controllerInfo = serviceClass.getCanonicalName() + "." + targetMethod.getName();
String action = "api:" + ASCII.toLowerCase(httpMethod.name()) + ":" + path;
context.httpServer.handler.route.add(httpMethod, path, new ControllerHolder(controller, targetMethod, controllerInfo, action, false));
} catch (NoSuchMethodException e) {
throw new Error("failed to find impl method", e);
}
}
apiController().serviceInterfaces.add(serviceInterface);
}
use of core.framework.api.web.service.Path in project core-ng-project by neowu.
the class WebServiceInterfaceValidator method validate.
private void validate(Method method) {
validateHTTPMethod(method);
HTTPMethod httpMethod = HTTPMethods.httpMethod(method);
Path path = method.getDeclaredAnnotation(Path.class);
if (path == null)
throw Exceptions.error("method must have @Path, method={}", method);
new PathPatternValidator(path.value()).validate();
validateResponseBeanType(method.getGenericReturnType());
Set<String> pathVariables = pathVariables(path.value());
Type requestBeanType = null;
Annotation[][] annotations = method.getParameterAnnotations();
Type[] paramTypes = method.getGenericParameterTypes();
Set<String> pathParams = Sets.newHashSet();
for (int i = 0; i < paramTypes.length; i++) {
Type paramType = paramTypes[i];
PathParam pathParam = Params.annotation(annotations[i], PathParam.class);
if (pathParam != null) {
validatePathParamType(paramType);
pathParams.add(pathParam.value());
} else {
if (requestBeanType != null)
throw Exceptions.error("service method must not have more than one bean param, previous={}, current={}", requestBeanType.getTypeName(), paramType.getTypeName());
requestBeanType = paramType;
if (httpMethod == HTTPMethod.GET || httpMethod == HTTPMethod.DELETE) {
requestBeanMapper.registerQueryParamBean(requestBeanType);
} else {
requestBeanMapper.registerRequestBean(requestBeanType);
}
}
}
if (pathVariables.size() != pathParams.size() || !pathVariables.containsAll(pathParams))
throw Exceptions.error("service method @PathParam params must match variable in path pattern, path={}, method={}", path.value(), method);
}
Aggregations