ninja-core/src/main/java/ninja/params/ControllerMethodInvoker.java
public static ControllerMethodInvoker build(
            Method functionalMethod, 
            Method implementationMethod, 
            Injector injector,
            NinjaProperties ninjaProperties) {
        // get both the parameters...
        final Type[] genericParameterTypes = implementationMethod.getGenericParameterTypes();
        final MethodParameter[] methodParameters = MethodParameter.convertIntoMethodParameters(genericParameterTypes);
        // ... and all annotations for the parameters
        final Annotation[][] paramAnnotations = implementationMethod
                .getParameterAnnotations();

        ArgumentExtractor<?>[] argumentExtractors = new ArgumentExtractor<?>[methodParameters.length];

        // now we skip through the parameters and process the annotations
        for (int i = 0; i < methodParameters.length; i++) {
            try {
                argumentExtractors[i] = getArgumentExtractor(methodParameters[i], paramAnnotations[i],
                        injector);
            } catch (RoutingException e) {
                throw new RoutingException("Error building argument extractor for parameter " + i +
                        " in method " + implementationMethod.getDeclaringClass().getName() + "." + implementationMethod.getName() + "()", e);
            }
        }

        // Replace a null extractor with a bodyAs extractor, but make sure there's only one
        int bodyAsFound = -1;
        for (int i = 0; i < argumentExtractors.length; i++) {
            if (argumentExtractors[i] == null) {
                if (bodyAsFound > -1) {
                    throw new RoutingException("Only one parameter may be deserialised as the body "
                            + implementationMethod.getDeclaringClass().getName() + "." + implementationMethod.getName() + "()\n"
                            + "Extracted parameter is type: " + methodParameters[bodyAsFound].parameterClass.getName() + "\n"
                            + "Extra parmeter is type: " + methodParameters[i].parameterClass.getName());
                } else {
                    argumentExtractors[i] = new ArgumentExtractors.BodyAsExtractor(methodParameters[i].parameterClass);
                    bodyAsFound = i;
                }
            }
        }

        // Now that every parameter has an argument extractor we can run validation on the annotated
        // parameters
        for (int i = 0; i < argumentExtractors.length; i++) {
            argumentExtractors[i] =
                    validateArgumentWithExtractor(
                            methodParameters[i],
                            paramAnnotations[i], 
                            injector,
                            argumentExtractors[i]);
        }
        
        boolean useStrictArgumentExtractors = determineWhetherToUseStrictArgumentExtractorMode(ninjaProperties);

        return new ControllerMethodInvoker(functionalMethod, argumentExtractors, useStrictArgumentExtractors);
    }
public static ControllerMethodInvoker build(
            Method functionalMethod, 
            Method implementationMethod, 
            Injector injector,
            NinjaProperties ninjaProperties) {
        // get both the parameters...
        final Type[] genericParameterTypes = implementationMethod.getGenericParameterTypes();
        final MethodParameter[] methodParameters = MethodParameter.convertIntoMethodParameters(genericParameterTypes);
        // ... and all annotations for the parameters
        final Annotation[][] paramAnnotations = implementationMethod
                .getParameterAnnotations();

        ArgumentExtractor<?>[] argumentExtractors = new ArgumentExtractor<?>[methodParameters.length];

        // now we skip through the parameters and process the annotations
        for (int i = 0; i < methodParameters.length; i++) {
            try {
                argumentExtractors[i] = getArgumentExtractor(methodParameters[i], paramAnnotations[i],
                        injector);
            } catch (RoutingException e) {
                throw new RoutingException("Error building argument extractor for parameter " + i +
                        " in method " + implementationMethod.getDeclaringClass().getName() + "." + implementationMethod.getName() + "()", e);
            }
        }

        // Replace a null extractor with a bodyAs extractor, but make sure there's only one
        int bodyAsFound = -1;
        for (int i = 0; i < argumentExtractors.length; i++) {
            if (argumentExtractors[i] == null) {
                if (bodyAsFound > -1) {
                    throw new RoutingException("Only one parameter may be deserialised as the body "
                            + implementationMethod.getDeclaringClass().getName() + "." + implementationMethod.getName() + "()\n"
                            + "Extracted parameter is type: " + methodParameters[bodyAsFound].parameterClass.getName() + "\n"
                            + "Extra parmeter is type: " + methodParameters[i].parameterClass.getName());
                } else {
                    argumentExtractors[i] = new ArgumentExtractors.BodyAsExtractor(methodParameters[i].parameterClass);
                    bodyAsFound = i;
                }
            }
        }

        // Now that every parameter has an argument extractor we can run validation on the annotated
        // parameters
        for (int i = 0; i < argumentExtractors.length; i++) {
            argumentExtractors[i] =
                    validateArgumentWithExtractor(
                            methodParameters[i],
                            paramAnnotations[i], 
                            injector,
                            argumentExtractors[i]);
        }
        
        boolean useStrictArgumentExtractors = determineWhetherToUseStrictArgumentExtractorMode(ninjaProperties);

        return new ControllerMethodInvoker(functionalMethod, argumentExtractors, useStrictArgumentExtractors);
    }
Builds an invoker for a functional method.  Understands what parameters
to inject and extract based on type and annotations.
@param functionalMethod The method to be invoked
@param implementationMethod The method to use for determining what
actual parameters and annotations to use for each argument.  Useful
when type/lambda erasure makes the functional interface not reliable
for reflecting.
@param injector The guice injector
@param ninjaProperties The NinjaProperties of this application
@return An invoker