Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright 2015-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
   *
   * Licensed under the Apache License, Version 2.0 (the "License").
   * You may not use this file except in compliance with the License.
   * A copy of the License is located at
   *
   *  http://aws.amazon.com/apache2.0
   *
  * or in the "license" file accompanying this file. This file 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.amazonaws.services.lambda.invoke;
 
 import java.util.List;
 
 
A factory for objects that implement a user-supplied interface by invoking a remote Lambda function.

public class Request { // Standard POJO stuff here modeling the input your Lambda function // expects. } public class Result { // More standard POJO stuff here modeling the output your Lambda // function produces. } public interface LambdaFunctions {

LambdaFunction:
Result doSomeStuff(Request request); } LambdaFunctions functions = LambdaInvokerFactory.build( LambdaFunctions.class, new AWSLambdaClient()); Request request = new Request(...); Result result = functions.doSomeStuff(request);
 
 public final class LambdaInvokerFactory {
 
     private static final ObjectMapper MAPPER = new ObjectMapper();

    
Creates a new Lambda invoker implementing the given interface and wrapping the given AWSLambda client.

Parameters:
interfaceClass the interface to implement
awsLambda the lambda client to use for making remote calls
 
     public static <T> T build(Class<T> interfaceClassAWSLambda awsLambda) {
         Object proxy = Proxy.newProxyInstance(
                 interfaceClass.getClassLoader(),
                 new Class<?>[] { interfaceClass },
                 new LambdaInvocationHandler(interfaceClassawsLambda));
 
         return interfaceClass.cast(proxy);
     }
 
     private LambdaInvokerFactory() {
     }
 
 
     private static class LambdaInvocationHandler implements InvocationHandler {
 
         private final AWSLambda awsLambda;
         private final Log log;
 
         public LambdaInvocationHandler(
                 Class<?> interfaceClass,
                AWSLambda awsLambda) {
            this. = awsLambda;
            this. = LogFactory.getLog(interfaceClass);
        }
        @Override
        public Object invoke(Object proxyMethod methodObject[] args)
                throws Throwable {
            LambdaFunction annotation = validateInterfaceMethod(methodargs);
            InvokeRequest invokeRequest = buildInvokeRequest(
                    method,
                    annotation,
                    args == null ? null : args[0]);
            InvokeResult invokeResult = .invoke(invokeRequest);
            return processInvokeResult(methodinvokeResult);
        }

        
Verifies that the given method is annotated appropriately.
        private LambdaFunction validateInterfaceMethod(
                Method method,
                Object[] args) {
            LambdaFunction annotation =
                method.getAnnotation(LambdaFunction.class);
            if (annotation == null) {
                throw new LambdaSerializationException(
                        "No LambdaFunction annotation for method "
                        + method.getName());
            }
            if (annotation.invocationType() != .
                    && annotation.logType() != .) {
                throw new LambdaSerializationException(
                        "InvocationType must be RequestResponse if LogType "
                        + "is set");
            }
            if (args != null && args.length > 1) {
                throw new LambdaSerializationException(
                        "LambdaFunctions take either 0 or 1 arguments");
            }
            return annotation;
        }

        
Builds an InvokeRequest from the given method, its LambdaFunction annotation, and the input parameter (if any).
        private InvokeRequest buildInvokeRequest(
                Method method,
                LambdaFunction annotation,
                Object input) {
            InvokeRequest invokeRequest = new InvokeRequest();
            String functionName = annotation.functionName();
            if (functionName.isEmpty()) {
                functionName = method.getName();
            }
            invokeRequest.setFunctionName(functionName);
            invokeRequest.setInvocationType(annotation.invocationType());
            invokeRequest.setLogType(annotation.logType());
            if (input != null) {
                try {
                    String payload = .writer().writeValueAsString(input);
                    if (.isDebugEnabled()) {
                        .debug("Serialized request object to '" + payload
                                + "'");
                    }
                    invokeRequest.setPayload(payload);
                } catch (JsonProcessingException ex) {
                    throw new LambdaSerializationException(
                            "Failed to serialize request object to JSON",
                            ex);
                }
            }
            return invokeRequest;
        }

        
Process the result of invoking a remote function. If the response includes server-side logs, dump them into our logs; if it includes a server-side error indication, parse it into a corresponding Exception type, otherwise parse the result payload into a Java object suitable for returning from this method.
        private Object processInvokeResult(
                Method method,
                InvokeResult invokeResultthrows Throwable {
            if (invokeResult.getLogResult() != null && .isInfoEnabled()) {
                try {
                    String decoded = new String(
                            Base64.decode(invokeResult.getLogResult()),
                            .);
                    .info(method.getName() + " log:\n\t"
                            + decoded.replaceAll("\n""\n\t"));
                } catch (Exception ex) {
                    .warn("Error decoding log result '"
                            + invokeResult.getLogResult() + "'",
                            ex);
                }
            }
            String functionError = invokeResult.getFunctionError();
            if (functionError == null) {
                // Success.
                return getObjectFromPayload(methodinvokeResult);
            } else {
                throw getExceptionFromPayload(methodinvokeResult);
            }
        }

        
Reads a Java object suitable for returning from the given method from the payload of the given InvokeResult (or returns null if the method has no return value or the response contains no payload).

Throws:
LambdaSerializationException on error deserializing
        private Object getObjectFromPayload(
                Method method,
                InvokeResult invokeResult) {
            try {
                return getObjectFromPayload(
                        method.getGenericReturnType(),
                        invokeResult.getPayload());
            } catch (IOException ex) {
                throw new LambdaSerializationException(
                        "Failed to parse Lambda function result",
                        ex);
            }
        }
        private Throwable getExceptionFromPayload(
                Method method,
                InvokeResult invokeResult) {
            Throwable throwable = null;
            String message = "Unexpected error executing Lambda function";
            String type = null;
            List<StringstackTrace = null;
            try {
                LambdaFunctionError error = getObjectFromPayload(
                        LambdaFunctionError.class,
                        invokeResult.getPayload());
                if (error != null) {
                    message = error.getErrorMessage();
                    type = error.getErrorType();
                    stackTrace = error.getStackTrace();
                    throwable = getCustomException(methoderror);
                }
            } catch (Exception ex) {
                .warn("Error parsing exception information from response "
                        + "payload",
                        ex);
            }
            if (throwable == null) {
                throwable = new LambdaFunctionException(
                        message,
                        "Handled".equals(invokeResult.getFunctionError()),
                        type);
            }
            if (stackTrace != null) {
                fillStackTrace(
                        throwable,
                        stackTrace,
                        method.getDeclaringClass());
            }
            return throwable;
        }
        private Throwable getCustomException(
                Method method,
                LambdaFunctionError error) {
            String type = error.getErrorType();
            Constructor<?> constructor = null;
            if (type != null) {
                for (Class<?> exceptionType : method.getExceptionTypes()) {
                    if (exceptionType.getSimpleName().startsWith(type)) {
                        constructor = findConstructor(exceptionType);
                        if (constructor != null) {
                            break;
                        }
                    }
                }
            }
            if (constructor != null) {
                try {
                    return (Throwableconstructor.newInstance(
                            error.getErrorMessage());
                } catch (Exception ex) {
                    .warn("Error constructing custom exception"ex);
                }
            }
            return null;
        }
        private Constructor<?> findConstructor(Class<?> type) {
            for (Constructor<?> constructor : type.getConstructors()) {
                Class<?>[] params = constructor.getParameterTypes();
                if (params != null
                        && params.length == 1
                        && String.class.equals(params[0])) {
                    return constructor;
                }
            }
            return null;
        }
        private void fillStackTrace(
                Throwable throwable,
                List<StringstackTrace,
                Class<?> interfaceClass) {
            StackTraceElement[] elements =
                    new StackTraceElement[stackTrace.size()];
            for (int i = 0; i < stackTrace.size(); ++i) {
                elements[i] = new StackTraceElement(
                        interfaceClass.getName(),
                        stackTrace.get(i).trim(),
                        null,
                        0);
            }
            throwable.setStackTrace(elements);
        }
        private <T> T getObjectFromPayload(Class<T> typeByteBuffer payload)
                throws IOException {
            return type.cast(getObjectFromPayload((Typetypepayload));
        }
        private Object getObjectFromPayload(
                Type type,
                ByteBuffer payloadthrows IOException {
            if (type == void.class || payload.remaining() == 0) {
                return null;
            }
            JavaType javaType = .getTypeFactory().constructType(type);
            return .reader(javaType).readValue(
                    BinaryUtils.copyAllBytesFrom(payload));
        }
    }
New to GrepCode? Check out our FAQ X