You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rp...@apache.org on 2015/08/09 18:16:58 UTC

[02/11] logging-log4j2 git commit: LOG4J2-599 - revert changes to Logger and ExtendedLogger interfaces; - add new interfaces LambdaLogger and ExtendedLambdaLogger that inherit from the existing interfaces and add lambda support - AbstractLogger implement

LOG4J2-599 
- revert changes to Logger and ExtendedLogger interfaces; 
- add new interfaces LambdaLogger and ExtendedLambdaLogger that inherit
from the existing interfaces and add lambda support
- AbstractLogger implements the new lambda support interfaces
- added factory methods to obtain LambdaLoggers from LogManager
- JUnit test for LambdaUtil

Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/914b291c
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/914b291c
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/914b291c

Branch: refs/heads/master
Commit: 914b291ce46a8224a2228c92740c51621b5b76b1
Parents: bccedde
Author: rpopma <rp...@apache.org>
Authored: Thu Aug 6 23:50:23 2015 +0900
Committer: rpopma <rp...@apache.org>
Committed: Thu Aug 6 23:50:23 2015 +0900

----------------------------------------------------------------------
 .../org/apache/logging/log4j/LambdaLogger.java  | 429 +++++++++++++++++++
 .../org/apache/logging/log4j/LogManager.java    | 128 +++++-
 .../java/org/apache/logging/log4j/Logger.java   |  14 -
 .../logging/log4j/spi/AbstractLogger.java       | 221 +++++++++-
 .../logging/log4j/spi/ExtendedLambdaLogger.java |  56 +++
 .../logging/log4j/spi/ExtendedLogger.java       |  26 --
 .../logging/log4j/util/LambdaUtilTest.java      | 119 +++++
 7 files changed, 926 insertions(+), 67 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/914b291c/log4j-api/src/main/java/org/apache/logging/log4j/LambdaLogger.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/LambdaLogger.java b/log4j-api/src/main/java/org/apache/logging/log4j/LambdaLogger.java
new file mode 100644
index 0000000..ea08013
--- /dev/null
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/LambdaLogger.java
@@ -0,0 +1,429 @@
+/*
+ * 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.logging.log4j;
+
+import java.util.concurrent.Callable;
+
+/**
+ * Extends the {@code Logger} interface with support for lambda expressions.
+ * <p>
+ * This logger allows client code to lazily log messages without explicitly checking if the requested log level is
+ * enabled. For example, previously one would write:
+ * 
+ * <pre>
+ * // pre-Java 8 style optimization: explicitly check the log level
+ * // to make sure the expensiveOperation() method is only called if necessary
+ * Logger logger = LogManager.getLogger();
+ * if (logger.isTraceEnabled()) {
+ *     logger.trace(&quot;Some long-running operation returned {}&quot;, expensiveOperation());
+ * }
+ * </pre>
+ * <p>
+ * With Java 8 and the {@code LambdaLogger} interface, one can achieve the same effect by using a lambda expression:
+ * 
+ * <pre>
+ * // Java-8 style optimization: no need to explicitly check the log level:
+ * // the lambda expression is not evaluated if the TRACE level is not enabled
+ * Logger2 logger = LogManager.getLambdaLogger();
+ * logger.trace(&quot;Some long-running operation returned {}&quot;, () -&gt; expensiveOperation());
+ * </pre>
+ */
+public interface LambdaLogger extends Logger {
+
+    /**
+     * Logs a message which is only to be constructed if the logging level is the {@link Level#DEBUG DEBUG} level.
+     *
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     */
+    void debug(Callable<?> msgSupplier);
+
+    /**
+     * Logs a message (only to be constructed if the logging level is the {@link Level#DEBUG DEBUG} level) including the
+     * stack trace of the {@link Throwable} <code>t</code> passed as parameter.
+     *
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     * @param t the exception to log, including its stack trace.
+     */
+    void debug(Callable<?> msgSupplier, Throwable t);
+
+    /**
+     * Logs a message which is only to be constructed if the logging level is the {@link Level#DEBUG DEBUG} level with
+     * the specified Marker.
+     *
+     * @param marker the marker data specific to this log statement
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     */
+    void debug(Marker marker, Callable<?> msgSupplier);
+
+    /**
+     * Logs a message (only to be constructed if the logging level is the {@link Level#DEBUG DEBUG} level) with the
+     * specified Marker and including the stack trace of the {@link Throwable} <code>t</code> passed as parameter.
+     *
+     * @param marker the marker data specific to this log statement
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     * @param t A Throwable or null.
+     */
+    void debug(Marker marker, Callable<?> msgSupplier, Throwable t);
+
+    /**
+     * Logs a message with parameters which are only to be constructed if the logging level is the {@link Level#DEBUG
+     * DEBUG} level.
+     *
+     * @param marker the marker data specific to this log statement
+     * @param message the message to log; the format depends on the message factory.
+     * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
+     */
+    void debug(Marker marker, String message, Callable<?>... paramSuppliers);
+
+    /**
+     * Logs a message with parameters which are only to be constructed if the logging level is the {@link Level#DEBUG
+     * DEBUG} level.
+     *
+     * @param message the message to log; the format depends on the message factory.
+     * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
+     */
+    void debug(String message, Callable<?>... paramSuppliers);
+
+    /**
+     * Logs a message which is only to be constructed if the logging level is the {@link Level#ERROR ERROR} level.
+     *
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     */
+    void error(Callable<?> msgSupplier);
+
+    /**
+     * Logs a message (only to be constructed if the logging level is the {@link Level#ERROR ERROR} level) including the
+     * stack trace of the {@link Throwable} <code>t</code> passed as parameter.
+     *
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     * @param t the exception to log, including its stack trace.
+     */
+    void error(Callable<?> msgSupplier, Throwable t);
+
+    /**
+     * Logs a message which is only to be constructed if the logging level is the {@link Level#ERROR ERROR} level with
+     * the specified Marker.
+     *
+     * @param marker the marker data specific to this log statement
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     */
+    void error(Marker marker, Callable<?> msgSupplier);
+
+    /**
+     * Logs a message (only to be constructed if the logging level is the {@link Level#ERROR ERROR} level) with the
+     * specified Marker and including the stack trace of the {@link Throwable} <code>t</code> passed as parameter.
+     *
+     * @param marker the marker data specific to this log statement
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     * @param t A Throwable or null.
+     */
+    void error(Marker marker, Callable<?> msgSupplier, Throwable t);
+
+    /**
+     * Logs a message with parameters which are only to be constructed if the logging level is the {@link Level#ERROR
+     * ERROR} level.
+     *
+     * @param marker the marker data specific to this log statement
+     * @param message the message to log; the format depends on the message factory.
+     * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
+     */
+    void error(Marker marker, String message, Callable<?>... paramSuppliers);
+
+    /**
+     * Logs a message with parameters which are only to be constructed if the logging level is the {@link Level#ERROR
+     * ERROR} level.
+     *
+     * @param message the message to log; the format depends on the message factory.
+     * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
+     */
+    void error(String message, Callable<?>... paramSuppliers);
+
+    /**
+     * Logs a message which is only to be constructed if the logging level is the {@link Level#FATAL FATAL} level.
+     *
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     */
+    void fatal(Callable<?> msgSupplier);
+
+    /**
+     * Logs a message (only to be constructed if the logging level is the {@link Level#FATAL FATAL} level) including the
+     * stack trace of the {@link Throwable} <code>t</code> passed as parameter.
+     *
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     * @param t the exception to log, including its stack trace.
+     */
+    void fatal(Callable<?> msgSupplier, Throwable t);
+
+    /**
+     * Logs a message which is only to be constructed if the logging level is the {@link Level#FATAL FATAL} level with
+     * the specified Marker.
+     *
+     * @param marker the marker data specific to this log statement
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     */
+    void fatal(Marker marker, Callable<?> msgSupplier);
+
+    /**
+     * Logs a message (only to be constructed if the logging level is the {@link Level#FATAL FATAL} level) with the
+     * specified Marker and including the stack trace of the {@link Throwable} <code>t</code> passed as parameter.
+     *
+     * @param marker the marker data specific to this log statement
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     * @param t A Throwable or null.
+     */
+    void fatal(Marker marker, Callable<?> msgSupplier, Throwable t);
+
+    /**
+     * Logs a message with parameters which are only to be constructed if the logging level is the {@link Level#FATAL
+     * FATAL} level.
+     *
+     * @param marker the marker data specific to this log statement
+     * @param message the message to log; the format depends on the message factory.
+     * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
+     */
+    void fatal(Marker marker, String message, Callable<?>... paramSuppliers);
+
+    /**
+     * Logs a message with parameters which are only to be constructed if the logging level is the {@link Level#FATAL
+     * FATAL} level.
+     *
+     * @param message the message to log; the format depends on the message factory.
+     * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
+     */
+    void fatal(String message, Callable<?>... paramSuppliers);
+
+    /**
+     * Logs a message which is only to be constructed if the logging level is the {@link Level#INFO INFO} level.
+     *
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     */
+    void info(Callable<?> msgSupplier);
+
+    /**
+     * Logs a message (only to be constructed if the logging level is the {@link Level#INFO INFO} level) including the
+     * stack trace of the {@link Throwable} <code>t</code> passed as parameter.
+     *
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     * @param t the exception to log, including its stack trace.
+     */
+    void info(Callable<?> msgSupplier, Throwable t);
+
+    /**
+     * Logs a message which is only to be constructed if the logging level is the {@link Level#INFO INFO} level with the
+     * specified Marker.
+     *
+     * @param marker the marker data specific to this log statement
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     */
+    void info(Marker marker, Callable<?> msgSupplier);
+
+    /**
+     * Logs a message (only to be constructed if the logging level is the {@link Level#INFO INFO} level) with the
+     * specified Marker and including the stack trace of the {@link Throwable} <code>t</code> passed as parameter.
+     *
+     * @param marker the marker data specific to this log statement
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     * @param t A Throwable or null.
+     */
+    void info(Marker marker, Callable<?> msgSupplier, Throwable t);
+
+    /**
+     * Logs a message with parameters which are only to be constructed if the logging level is the {@link Level#INFO
+     * INFO} level.
+     *
+     * @param marker the marker data specific to this log statement
+     * @param message the message to log; the format depends on the message factory.
+     * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
+     */
+    void info(Marker marker, String message, Callable<?>... paramSuppliers);
+
+    /**
+     * Logs a message with parameters which are only to be constructed if the logging level is the {@link Level#INFO
+     * INFO} level.
+     *
+     * @param message the message to log; the format depends on the message factory.
+     * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
+     */
+    void info(String message, Callable<?>... paramSuppliers);
+
+    /**
+     * Logs a message which is only to be constructed if the logging level is the specified level.
+     *
+     * @param level the logging level
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     */
+    void log(Level level, Callable<?> msgSupplier);
+
+    /**
+     * Logs a message (only to be constructed if the logging level is the specified level) including the stack log of
+     * the {@link Throwable} <code>t</code> passed as parameter.
+     *
+     * @param level the logging level
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     * @param t the exception to log, including its stack log.
+     */
+    void log(Level level, Callable<?> msgSupplier, Throwable t);
+
+    /**
+     * Logs a message (only to be constructed if the logging level is the specified level) with the specified Marker.
+     *
+     * @param level the logging level
+     * @param marker the marker data specific to this log statement
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     */
+    void log(Level level, Marker marker, Callable<?> msgSupplier);
+
+    /**
+     * Logs a message (only to be constructed if the logging level is the specified level) with the specified Marker and
+     * including the stack log of the {@link Throwable} <code>t</code> passed as parameter.
+     *
+     * @param level the logging level
+     * @param marker the marker data specific to this log statement
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     * @param t A Throwable or null.
+     */
+    void log(Level level, Marker marker, Callable<?> msgSupplier, Throwable t);
+
+    /**
+     * Logs a message with parameters which are only to be constructed if the logging level is the specified level.
+     *
+     * @param level the logging level
+     * @param marker the marker data specific to this log statement
+     * @param message the message to log; the format depends on the message factory.
+     * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
+     */
+    void log(Level level, Marker marker, String message, Callable<?>... paramSuppliers);
+
+    /**
+     * Logs a message with parameters which are only to be constructed if the logging level is the specified level.
+     *
+     * @param level the logging level
+     * @param message the message to log; the format depends on the message factory.
+     * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
+     */
+    void log(Level level, String message, Callable<?>... paramSuppliers);
+
+    /**
+     * Logs a message which is only to be constructed if the logging level is the {@link Level#TRACE TRACE} level.
+     *
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     */
+    void trace(Callable<?> msgSupplier);
+
+    /**
+     * Logs a message (only to be constructed if the logging level is the {@link Level#TRACE TRACE} level) including the
+     * stack trace of the {@link Throwable} <code>t</code> passed as parameter.
+     *
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     * @param t the exception to log, including its stack trace.
+     */
+    void trace(Callable<?> msgSupplier, Throwable t);
+
+    /**
+     * Logs a message which is only to be constructed if the logging level is the {@link Level#TRACE TRACE} level with
+     * the specified Marker.
+     *
+     * @param marker the marker data specific to this log statement
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     */
+    void trace(Marker marker, Callable<?> msgSupplier);
+
+    /**
+     * Logs a message (only to be constructed if the logging level is the {@link Level#TRACE TRACE} level) with the
+     * specified Marker and including the stack trace of the {@link Throwable} <code>t</code> passed as parameter.
+     *
+     * @param marker the marker data specific to this log statement
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     * @param t A Throwable or null.
+     */
+    void trace(Marker marker, Callable<?> msgSupplier, Throwable t);
+
+    /**
+     * Logs a message with parameters which are only to be constructed if the logging level is the {@link Level#TRACE
+     * TRACE} level.
+     *
+     * @param marker the marker data specific to this log statement
+     * @param message the message to log; the format depends on the message factory.
+     * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
+     */
+    void trace(Marker marker, String message, Callable<?>... paramSuppliers);
+
+    /**
+     * Logs a message with parameters which are only to be constructed if the logging level is the {@link Level#TRACE
+     * TRACE} level.
+     *
+     * @param message the message to log; the format depends on the message factory.
+     * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
+     */
+    void trace(String message, Callable<?>... paramSuppliers);
+
+    /**
+     * Logs a message which is only to be constructed if the logging level is the {@link Level#WARN WARN} level.
+     *
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     */
+    void warn(Callable<?> msgSupplier);
+
+    /**
+     * Logs a message (only to be constructed if the logging level is the {@link Level#WARN WARN} level) including the
+     * stack warn of the {@link Throwable} <code>t</code> passed as parameter.
+     *
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     * @param t the exception to log, including its stack warn.
+     */
+    void warn(Callable<?> msgSupplier, Throwable t);
+
+    /**
+     * Logs a message which is only to be constructed if the logging level is the {@link Level#WARN WARN} level with the
+     * specified Marker.
+     *
+     * @param marker the marker data specific to this log statement
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     */
+    void warn(Marker marker, Callable<?> msgSupplier);
+
+    /**
+     * Logs a message (only to be constructed if the logging level is the {@link Level#WARN WARN} level) with the
+     * specified Marker and including the stack warn of the {@link Throwable} <code>t</code> passed as parameter.
+     *
+     * @param marker the marker data specific to this log statement
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     * @param t A Throwable or null.
+     */
+    void warn(Marker marker, Callable<?> msgSupplier, Throwable t);
+
+    /**
+     * Logs a message with parameters which are only to be constructed if the logging level is the {@link Level#WARN
+     * WARN} level.
+     *
+     * @param marker the marker data specific to this log statement
+     * @param message the message to log; the format depends on the message factory.
+     * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
+     */
+    void warn(Marker marker, String message, Callable<?>... paramSuppliers);
+
+    /**
+     * Logs a message with parameters which are only to be constructed if the logging level is the {@link Level#WARN
+     * WARN} level.
+     *
+     * @param message the message to log; the format depends on the message factory.
+     * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
+     */
+    void warn(String message, Callable<?>... paramSuppliers);
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/914b291c/log4j-api/src/main/java/org/apache/logging/log4j/LogManager.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/LogManager.java b/log4j-api/src/main/java/org/apache/logging/log4j/LogManager.java
index d5ad911..f4aa848 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/LogManager.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/LogManager.java
@@ -416,6 +416,114 @@ public class LogManager {
     }
 
     /**
+     * Returns a LambdaLogger with the name of the calling class.
+     * @return The LambdaLogger for the calling class.
+     * @throws UnsupportedOperationException if the calling class cannot be determined.
+     */
+    public static LambdaLogger getLambdaLogger() {
+        return (LambdaLogger) getLogger(ReflectionUtil.getCallerClass(2));
+    }
+    
+    private static Class<?> callerClass(final Class<?> clazz) {
+        if (clazz != null) {
+            return clazz;
+        }
+        final Class<?> candidate = ReflectionUtil.getCallerClass(3);
+        if (candidate == null) {
+            throw new UnsupportedOperationException("No class provided, and an appropriate one cannot be found.");
+        }
+        return candidate;
+    }
+
+    /**
+     * Returns a LambdaLogger using the fully qualified name of the Class as the Logger name.
+     * @param clazz The Class whose name should be used as the Logger name. If null it will default to the calling
+     *              class.
+     * @return The LambdaLogger.
+     * @throws UnsupportedOperationException if {@code clazz} is {@code null} and the calling class cannot be determined.
+     */
+    public static LambdaLogger getLambdaLogger(final Class<?> clazz) {
+        final Class<?> cls = callerClass(clazz);
+        return (LambdaLogger) getContext(cls.getClassLoader(), false).getLogger(cls.getName());
+    }
+
+    /**
+     * Returns a LambdaLogger using the fully qualified name of the Class as the Logger name.
+     * @param clazz The Class whose name should be used as the Logger name. If null it will default to the calling
+     *              class.
+     * @param messageFactory The message factory is used only when creating a logger, subsequent use does not change
+     *                       the logger but will log a warning if mismatched.
+     * @return The LambdaLogger.
+     * @throws UnsupportedOperationException if {@code clazz} is {@code null} and the calling class cannot be determined.
+     */
+    public static LambdaLogger getLambdaLogger(final Class<?> clazz, final MessageFactory messageFactory) {
+        final Class<?> cls = callerClass(clazz);
+        return (LambdaLogger) getContext(cls.getClassLoader(), false).getLogger(cls.getName(), messageFactory);
+    }
+
+    /**
+     * Returns a LambdaLogger with the name of the calling class.
+     * @param messageFactory The message factory is used only when creating a logger, subsequent use does not change
+     *                       the logger but will log a warning if mismatched.
+     * @return The LambdaLogger for the calling class.
+     * @throws UnsupportedOperationException if the calling class cannot be determined.
+     */
+    public static LambdaLogger getLambdaLogger(final MessageFactory messageFactory) {
+        return (LambdaLogger) getLogger(ReflectionUtil.getCallerClass(2), messageFactory);
+    }
+
+    /**
+     * Returns a LambdaLogger using the fully qualified class name of the value as the Logger name.
+     * @param value The value whose class name should be used as the Logger name. If null the name of the calling
+     *              class will be used as the logger name.
+     * @return The LambdaLogger.
+     * @throws UnsupportedOperationException if {@code value} is {@code null} and the calling class cannot be determined.
+     */
+    public static LambdaLogger getLambdaLogger(final Object value) {
+        return (LambdaLogger) getLogger(value != null ? value.getClass() : ReflectionUtil.getCallerClass(2));
+    }
+
+    /**
+     * Returns a LambdaLogger using the fully qualified class name of the value as the Logger name.
+     * @param value The value whose class name should be used as the Logger name. If null the name of the calling
+     *              class will be used as the logger name.
+     * @param messageFactory The message factory is used only when creating a logger, subsequent use does not change
+     *                       the logger but will log a warning if mismatched.
+     * @return The LambdaLogger.
+     * @throws UnsupportedOperationException if {@code value} is {@code null} and the calling class cannot be determined.
+     */
+    public static LambdaLogger getLambdaLogger(final Object value, final MessageFactory messageFactory) {
+        return (LambdaLogger) getLogger(value != null ? value.getClass() : ReflectionUtil.getCallerClass(2),
+                messageFactory);
+    }
+
+    /**
+     * Returns a LambdaLogger with the specified name.
+     *
+     * @param name The logger name. If null the name of the calling class will be used.
+     * @return The LambdaLogger.
+     * @throws UnsupportedOperationException if {@code name} is {@code null} and the calling class cannot be determined.
+     */
+    public static LambdaLogger getLambdaLogger(final String name) {
+        return (LambdaLogger) (name != null ? getContext(false).getLogger(name) : getLogger(
+                ReflectionUtil.getCallerClass(2)));
+    }
+
+    /**
+     * Returns a LambdaLogger with the specified name.
+     *
+     * @param name The logger name. If null the name of the calling class will be used.
+     * @param messageFactory The message factory is used only when creating a logger, subsequent use does not change
+     *                       the logger but will log a warning if mismatched.
+     * @return The LambdaLogger.
+     * @throws UnsupportedOperationException if {@code name} is {@code null} and the calling class cannot be determined.
+     */
+    public static LambdaLogger getLambdaLogger(final String name, final MessageFactory messageFactory) {
+        return (LambdaLogger) (name != null ? getContext(false).getLogger(name, messageFactory) : getLogger(
+            ReflectionUtil.getCallerClass(2), messageFactory));
+    }
+
+    /**
      * Returns a Logger with the name of the calling class.
      * @return The Logger for the calling class.
      * @throws UnsupportedOperationException if the calling class cannot be determined.
@@ -432,14 +540,8 @@ public class LogManager {
      * @throws UnsupportedOperationException if {@code clazz} is {@code null} and the calling class cannot be determined.
      */
     public static Logger getLogger(final Class<?> clazz) {
-        if (clazz == null) {
-            final Class<?> candidate = ReflectionUtil.getCallerClass(2);
-            if (candidate == null) {
-                throw new UnsupportedOperationException("No class provided, and an appropriate one cannot be found.");
-            }
-            return getLogger(candidate);
-        }
-        return getContext(clazz.getClassLoader(), false).getLogger(clazz.getName());
+        final Class<?> cls = callerClass(clazz);
+        return getContext(cls.getClassLoader(), false).getLogger(cls.getName());
     }
 
     /**
@@ -452,14 +554,8 @@ public class LogManager {
      * @throws UnsupportedOperationException if {@code clazz} is {@code null} and the calling class cannot be determined.
      */
     public static Logger getLogger(final Class<?> clazz, final MessageFactory messageFactory) {
-        if (clazz == null) {
-            final Class<?> candidate = ReflectionUtil.getCallerClass(2);
-            if (candidate == null) {
-                throw new UnsupportedOperationException("No class provided, and an appropriate one cannot be found.");
-            }
-            return getLogger(candidate, messageFactory);
-        }
-        return getContext(clazz.getClassLoader(), false).getLogger(clazz.getName(), messageFactory);
+        final Class<?> cls = callerClass(clazz);
+        return getContext(cls.getClassLoader(), false).getLogger(cls.getName(), messageFactory);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/914b291c/log4j-api/src/main/java/org/apache/logging/log4j/Logger.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/Logger.java b/log4j-api/src/main/java/org/apache/logging/log4j/Logger.java
index 85364b3..9c6d000 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/Logger.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/Logger.java
@@ -185,20 +185,6 @@ public interface Logger {
     void debug(String message, Throwable t);
 
     /**
-     * Logs a message which is only to be constructed if the logging level is the {@link Level#DEBUG DEBUG} level.
-     *
-     * @param msgSupplier A function, which when called, produces the desired log message.
-     */
-    void debug(Callable<?> msgSupplier);
-
-    /**
-     * Logs a message which is only to be constructed if the logging level is the {@link Level#DEBUG DEBUG} level.
-     *
-     * @param paramSupplier An array of functions, which when called, produce the desired log message parameters.
-     */
-    void debug(String message, Callable<?>... paramSupplier);
-
-    /**
      * Logs entry to a method. Used when the method in question has no parameters or when the parameters should not be
      * logged.
      */

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/914b291c/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java
index 4eb4a50..95696af 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java
@@ -32,7 +32,7 @@ import org.apache.logging.log4j.util.LambdaUtil;
 /**
  * Base implementation of a Logger. It is highly recommended that any Logger implementation extend this class.
  */
-public abstract class AbstractLogger implements ExtendedLogger, Serializable {
+public abstract class AbstractLogger implements ExtendedLambdaLogger, Serializable {
 
     private static final long serialVersionUID = 2L;
 
@@ -220,16 +220,6 @@ public abstract class AbstractLogger implements ExtendedLogger, Serializable {
     }
 
     @Override
-    public void debug(Callable<?> msgSupplier) {
-        logIfEnabled(FQCN, Level.DEBUG, null, msgSupplier, null);
-    }
-
-    @Override
-    public void debug(String message, Callable<?>... paramSupplier) {
-        logIfEnabled(FQCN, Level.DEBUG, null, message, paramSupplier);
-    }
-
-    @Override
     public void debug(final Object message) {
         logIfEnabled(FQCN, Level.DEBUG, null, message, null);
     }
@@ -255,6 +245,36 @@ public abstract class AbstractLogger implements ExtendedLogger, Serializable {
     }
 
     @Override
+    public void debug(final Callable<?> msgSupplier) {
+        logIfEnabled(FQCN, Level.DEBUG, null, msgSupplier, (Throwable) null);
+    }
+
+    @Override
+    public void debug(final Callable<?> msgSupplier, final Throwable t) {
+        logIfEnabled(FQCN, Level.DEBUG, null, msgSupplier, t);
+    }
+
+    @Override
+    public void debug(final Marker marker, final Callable<?> msgSupplier) {
+        logIfEnabled(FQCN, Level.DEBUG, marker, msgSupplier, (Throwable) null);
+    }
+
+    @Override
+    public void debug(final Marker marker, final String message, final Callable<?>... paramSuppliers) {
+        logIfEnabled(FQCN, Level.DEBUG, marker, message, paramSuppliers);
+    }
+
+    @Override
+    public void debug(final Marker marker, final Callable<?> msgSupplier, final Throwable t) {
+        logIfEnabled(FQCN, Level.DEBUG, marker, msgSupplier, t);
+    }
+
+    @Override
+    public void debug(final String message, final Callable<?>... paramSuppliers) {
+        logIfEnabled(FQCN, Level.DEBUG, null, message, paramSuppliers);
+    }
+
+    @Override
     public void entry() {
         entry(FQCN);
     }
@@ -367,6 +387,36 @@ public abstract class AbstractLogger implements ExtendedLogger, Serializable {
     }
 
     @Override
+    public void error(final Callable<?> msgSupplier) {
+        logIfEnabled(FQCN, Level.ERROR, null, msgSupplier, (Throwable) null);
+    }
+
+    @Override
+    public void error(final Callable<?> msgSupplier, final Throwable t) {
+        logIfEnabled(FQCN, Level.ERROR, null, msgSupplier, t);
+    }
+
+    @Override
+    public void error(final Marker marker, final Callable<?> msgSupplier) {
+        logIfEnabled(FQCN, Level.ERROR, marker, msgSupplier, (Throwable) null);
+    }
+
+    @Override
+    public void error(final Marker marker, final String message, final Callable<?>... paramSuppliers) {
+        logIfEnabled(FQCN, Level.ERROR, marker, message, paramSuppliers);
+    }
+
+    @Override
+    public void error(final Marker marker, final Callable<?> msgSupplier, final Throwable t) {
+        logIfEnabled(FQCN, Level.ERROR, marker, msgSupplier, t);
+    }
+
+    @Override
+    public void error(final String message, final Callable<?>... paramSuppliers) {
+        logIfEnabled(FQCN, Level.ERROR, null, message, paramSuppliers);
+    }
+
+    @Override
     public void exit() {
         exit(FQCN, null);
     }
@@ -469,6 +519,36 @@ public abstract class AbstractLogger implements ExtendedLogger, Serializable {
     }
 
     @Override
+    public void fatal(final Callable<?> msgSupplier) {
+        logIfEnabled(FQCN, Level.FATAL, null, msgSupplier, (Throwable) null);
+    }
+
+    @Override
+    public void fatal(final Callable<?> msgSupplier, final Throwable t) {
+        logIfEnabled(FQCN, Level.FATAL, null, msgSupplier, t);
+    }
+
+    @Override
+    public void fatal(final Marker marker, final Callable<?> msgSupplier) {
+        logIfEnabled(FQCN, Level.FATAL, marker, msgSupplier, (Throwable) null);
+    }
+
+    @Override
+    public void fatal(final Marker marker, final String message, final Callable<?>... paramSuppliers) {
+        logIfEnabled(FQCN, Level.FATAL, marker, message, paramSuppliers);
+    }
+
+    @Override
+    public void fatal(final Marker marker, final Callable<?> msgSupplier, final Throwable t) {
+        logIfEnabled(FQCN, Level.FATAL, marker, msgSupplier, t);
+    }
+
+    @Override
+    public void fatal(final String message, final Callable<?>... paramSuppliers) {
+        logIfEnabled(FQCN, Level.FATAL, null, message, paramSuppliers);
+    }
+
+    @Override
     public MessageFactory getMessageFactory() {
         return messageFactory;
     }
@@ -549,6 +629,36 @@ public abstract class AbstractLogger implements ExtendedLogger, Serializable {
     }
 
     @Override
+    public void info(final Callable<?> msgSupplier) {
+        logIfEnabled(FQCN, Level.INFO, null, msgSupplier, (Throwable) null);
+    }
+
+    @Override
+    public void info(final Callable<?> msgSupplier, final Throwable t) {
+        logIfEnabled(FQCN, Level.INFO, null, msgSupplier, t);
+    }
+
+    @Override
+    public void info(final Marker marker, final Callable<?> msgSupplier) {
+        logIfEnabled(FQCN, Level.INFO, marker, msgSupplier, (Throwable) null);
+    }
+
+    @Override
+    public void info(final Marker marker, final String message, final Callable<?>... paramSuppliers) {
+        logIfEnabled(FQCN, Level.INFO, marker, message, paramSuppliers);
+    }
+
+    @Override
+    public void info(final Marker marker, final Callable<?> msgSupplier, final Throwable t) {
+        logIfEnabled(FQCN, Level.INFO, marker, msgSupplier, t);
+    }
+
+    @Override
+    public void info(final String message, final Callable<?>... paramSuppliers) {
+        logIfEnabled(FQCN, Level.INFO, null, message, paramSuppliers);
+    }
+
+    @Override
     public boolean isDebugEnabled() {
         return isEnabled(Level.DEBUG, null, null);
     }
@@ -691,6 +801,36 @@ public abstract class AbstractLogger implements ExtendedLogger, Serializable {
     }
 
     @Override
+    public void log(final Level level, final Callable<?> msgSupplier) {
+        logIfEnabled(FQCN, level, null, msgSupplier, (Throwable) null);
+    }
+
+    @Override
+    public void log(final Level level, final Callable<?> msgSupplier, final Throwable t) {
+        logIfEnabled(FQCN, level, null, msgSupplier, t);
+    }
+
+    @Override
+    public void log(final Level level, final Marker marker, final Callable<?> msgSupplier) {
+        logIfEnabled(FQCN, level, marker, msgSupplier, (Throwable) null);
+    }
+
+    @Override
+    public void log(final Level level, final Marker marker, final String message, final Callable<?>... paramSuppliers) {
+        logIfEnabled(FQCN, level, marker, message, paramSuppliers);
+    }
+
+    @Override
+    public void log(final Level level, final Marker marker, final Callable<?> msgSupplier, final Throwable t) {
+        logIfEnabled(FQCN, level, marker, msgSupplier, t);
+    }
+
+    @Override
+    public void log(final Level level, final String message, final Callable<?>... paramSuppliers) {
+        logIfEnabled(FQCN, level, null, message, paramSuppliers);
+    }
+
+    @Override
     public void logIfEnabled(final String fqcn, final Level level, final Marker marker, final Message msg,
             final Throwable t) {
         if (isEnabled(level, marker, msg, t)) {
@@ -900,6 +1040,36 @@ public abstract class AbstractLogger implements ExtendedLogger, Serializable {
     }
 
     @Override
+    public void trace(final Callable<?> msgSupplier) {
+        logIfEnabled(FQCN, Level.TRACE, null, msgSupplier, (Throwable) null);
+    }
+
+    @Override
+    public void trace(final Callable<?> msgSupplier, final Throwable t) {
+        logIfEnabled(FQCN, Level.TRACE, null, msgSupplier, t);
+    }
+
+    @Override
+    public void trace(final Marker marker, final Callable<?> msgSupplier) {
+        logIfEnabled(FQCN, Level.TRACE, marker, msgSupplier, (Throwable) null);
+    }
+
+    @Override
+    public void trace(final Marker marker, final String message, final Callable<?>... paramSuppliers) {
+        logIfEnabled(FQCN, Level.TRACE, marker, message, paramSuppliers);
+    }
+
+    @Override
+    public void trace(final Marker marker, final Callable<?> msgSupplier, final Throwable t) {
+        logIfEnabled(FQCN, Level.TRACE, marker, msgSupplier, t);
+    }
+
+    @Override
+    public void trace(final String message, final Callable<?>... paramSuppliers) {
+        logIfEnabled(FQCN, Level.TRACE, null, message, paramSuppliers);
+    }
+
+    @Override
     public void warn(final Marker marker, final Message msg, final Throwable t) {
         logIfEnabled(FQCN, Level.WARN, marker, msg, t);
     }
@@ -969,4 +1139,33 @@ public abstract class AbstractLogger implements ExtendedLogger, Serializable {
         logIfEnabled(FQCN, Level.WARN, null, message, t);
     }
 
+    @Override
+    public void warn(final Callable<?> msgSupplier) {
+        logIfEnabled(FQCN, Level.WARN, null, msgSupplier, (Throwable) null);
+    }
+
+    @Override
+    public void warn(final Callable<?> msgSupplier, final Throwable t) {
+        logIfEnabled(FQCN, Level.WARN, null, msgSupplier, t);
+    }
+
+    @Override
+    public void warn(final Marker marker, final Callable<?> msgSupplier) {
+        logIfEnabled(FQCN, Level.WARN, marker, msgSupplier, (Throwable) null);
+    }
+
+    @Override
+    public void warn(final Marker marker, final String message, final Callable<?>... paramSuppliers) {
+        logIfEnabled(FQCN, Level.WARN, marker, message, paramSuppliers);
+    }
+
+    @Override
+    public void warn(final Marker marker, final Callable<?> msgSupplier, final Throwable t) {
+        logIfEnabled(FQCN, Level.WARN, marker, msgSupplier, t);
+    }
+
+    @Override
+    public void warn(final String message, final Callable<?>... paramSuppliers) {
+        logIfEnabled(FQCN, Level.WARN, null, message, paramSuppliers);
+    }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/914b291c/log4j-api/src/main/java/org/apache/logging/log4j/spi/ExtendedLambdaLogger.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/ExtendedLambdaLogger.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/ExtendedLambdaLogger.java
new file mode 100644
index 0000000..5e61f62
--- /dev/null
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/ExtendedLambdaLogger.java
@@ -0,0 +1,56 @@
+/*
+ * 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.logging.log4j.spi;
+
+import java.util.concurrent.Callable;
+
+import org.apache.logging.log4j.LambdaLogger;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+
+/**
+ * Extends the {@code LambdaLogger} interface with methods that facilitate implementing or extending
+ * {@code LambdaLogger}s. Users should not need to use this interface.
+ */
+public interface ExtendedLambdaLogger extends ExtendedLogger, LambdaLogger {
+
+    /**
+     * Logs a message whose parameters are only to be constructed if the specified level is active.
+     * 
+     * @param fqcn The fully qualified class name of the logger entry point, used to determine the caller class and
+     *            method when location information needs to be logged.
+     * @param level The logging Level to check.
+     * @param marker A Marker or null.
+     * @param message The message format.
+     * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
+     */
+    void logIfEnabled(String fqcn, Level level, Marker marker, String message, Callable<?>... paramSuppliers);
+
+    /**
+     * Logs a message which is only to be constructed if the specified level is active.
+     * 
+     * @param fqcn The fully qualified class name of the logger entry point, used to determine the caller class and
+     *            method when location information needs to be logged.
+     * @param level The logging Level to check.
+     * @param marker A Marker or null.
+     * @param msgSupplier A function, which when called, produces the desired log message.
+     * @param t the exception to log, including its stack trace.
+     */
+    void logIfEnabled(String fqcn, Level level, Marker marker, Callable<?> msgSupplier, Throwable t);
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/914b291c/log4j-api/src/main/java/org/apache/logging/log4j/spi/ExtendedLogger.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/ExtendedLogger.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/ExtendedLogger.java
index 1771f37..8a36c57 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/ExtendedLogger.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/ExtendedLogger.java
@@ -16,8 +16,6 @@
  */
 package org.apache.logging.log4j.spi;
 
-import java.util.concurrent.Callable;
-
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.Marker;
@@ -96,18 +94,6 @@ public interface ExtendedLogger extends Logger {
     void logIfEnabled(String fqcn, Level level, Marker marker, Message message, Throwable t);
 
     /**
-     * Logs a message which is only to be constructed if the specified level is active.
-     * 
-     * @param fqcn The fully qualified class name of the logger entry point, used to determine the caller class and
-     *            method when location information needs to be logged.
-     * @param level The logging Level to check.
-     * @param marker A Marker or null.
-     * @param msgSupplier A function, which when called, produces the desired log message.
-     * @param t the exception to log, including its stack trace.
-     */
-    void logIfEnabled(String fqcn, Level level, Marker marker, Callable<?> msgSupplier, Throwable t);
-
-    /**
      * Logs a message if the specified level is active.
      * 
      * @param fqcn The fully qualified class name of the logger entry point, used to determine the caller class and
@@ -155,18 +141,6 @@ public interface ExtendedLogger extends Logger {
     void logIfEnabled(String fqcn, Level level, Marker marker, String message, Object... params);
 
     /**
-     * Logs a message which is only to be constructed if the specified level is active.
-     * 
-     * @param fqcn The fully qualified class name of the logger entry point, used to determine the caller class and
-     *            method when location information needs to be logged.
-     * @param level The logging Level to check.
-     * @param marker A Marker or null.
-     * @param message The message format.
-     * @param paramSupplier An array of functions, which when called, produce the desired log message parameters.
-     */
-    void logIfEnabled(String fqcn, Level level, Marker marker, String message, Callable<?>... paramSuppliers);
-
-    /**
      * Always logs a message at the specified level. It is the responsibility of the caller to ensure the specified
      * level is enabled.
      * 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/914b291c/log4j-api/src/test/java/org/apache/logging/log4j/util/LambdaUtilTest.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/test/java/org/apache/logging/log4j/util/LambdaUtilTest.java b/log4j-api/src/test/java/org/apache/logging/log4j/util/LambdaUtilTest.java
new file mode 100644
index 0000000..edfc50e
--- /dev/null
+++ b/log4j-api/src/test/java/org/apache/logging/log4j/util/LambdaUtilTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.logging.log4j.util;
+
+import java.util.concurrent.Callable;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests the LambdaUtil class.
+ */
+public class LambdaUtilTest {
+
+    @Test
+    public void testCallReturnsResultOfCallable() {
+        final String expected = "result";
+        final Object actual = LambdaUtil.call(new Callable<String>() {
+            public String call() {
+                return expected;
+            }
+        });
+        assertSame(expected, actual);
+    }
+
+    @Test
+    public void testCallReturnsNullIfCallableNull() {
+        final Object actual = LambdaUtil.call(null);
+        assertNull(actual);
+    }
+
+    @Test
+    public void testCallReturnsExceptionIfCallableThrowsException() {
+        final Exception expected = new RuntimeException();
+        final Object actual = LambdaUtil.call(new Callable<String>() {
+            public String call() throws Exception{
+                throw expected;
+            }
+        });
+        assertSame(expected, actual);
+    }
+
+
+    @Test
+    public void testCallAllReturnsResultOfCallables() {
+        final String expected1 = "result1";
+        Callable<String> function1 = new Callable<String>() {
+            public String call() {
+                return expected1;
+            }
+        };
+        final String expected2 = "result2";
+        Callable<String> function2 = new Callable<String>() {
+            public String call() {
+                return expected2;
+            }
+        };
+        
+        Callable<?>[] functions = {function1, function2};
+        final Object[] actual = LambdaUtil.callAll(functions);
+        assertEquals(actual.length, functions.length);
+        assertSame(expected1, actual[0]);
+        assertSame(expected2, actual[1]);
+    }
+
+    @Test
+    public void testCallAllReturnsNullArrayIfCallablesArrayNull() {
+        final Object[] actual = LambdaUtil.callAll((Callable<?>[]) null);
+        assertNull(actual);
+    }
+
+    @Test
+    public void testCallAllReturnsNullElementsIfCallableArrayContainsNulls() {
+        final Callable<?>[] functions = new Callable[3];
+        final Object[] actual = LambdaUtil.callAll(functions);
+        assertEquals(actual.length, functions.length);
+        for (Object object : actual) {
+            assertNull(object);
+        }
+    }
+
+    @Test
+    public void testCallAllReturnsExceptionsIfCallablesThrowsException() {
+        final Exception expected1 = new RuntimeException();
+        Callable<String> function1 = new Callable<String>() {
+            public String call() throws Exception{
+                throw expected1;
+            }
+        };
+        final Exception expected2 = new RuntimeException();
+        Callable<String> function2 = new Callable<String>() {
+            public String call() throws Exception{
+                throw expected2;
+            }
+        };
+        
+        Callable<?>[] functions = {function1, function2};
+        final Object[] actual = LambdaUtil.callAll(functions);
+        assertEquals(actual.length, functions.length);
+        assertSame(expected1, actual[0]);
+        assertSame(expected2, actual[1]);
+    }
+}