You only see ^M characters when the file has mixed line endings. Git handles EOL settings differently than svn. In git, you could use git attributes <https://git-scm.com/docs/gitattributes> to enforce line endings. There's also EditorConfig <http://editorconfig.org/> which is more IDE-specific than git-specific.
There is also the git config option core.autocrlf. More info: < https://help.github.com/articles/dealing-with-line-endings/> On 12 April 2016 at 14:31, Gary Gregory <[email protected]> wrote: > Isn't there a git setting to checkout as Unix line-endings? Or was that in > Svn? > > Gary > > On Tue, Apr 12, 2016 at 12:28 PM, Ralph Goers <[email protected]> > wrote: > >> I thought we had standardized on unix line endings. I don’t recall >> seeing ^M characters in the files. My IDE automatically converts Windows >> crap to Unix. >> >> Ralph >> >> On Apr 12, 2016, at 12:12 PM, Gary Gregory <[email protected]> >> wrote: >> >> How frugal of you! ;-) I edit on Windows, so that's a two-fer for me ;-) >> >> Gary >> >> On Tue, Apr 12, 2016 at 12:04 PM, Matt Sicker <[email protected]> wrote: >> >>> I like unix endings because there's only one byte instead of two. >>> >>> On 12 April 2016 at 14:02, Gary Gregory <[email protected]> wrote: >>> >>>> Sure, pick one. >>>> >>>> Gary >>>> >>>> On Tue, Apr 12, 2016 at 12:01 PM, Matt Sicker <[email protected]> wrote: >>>> >>>>> It would be nice to standardize on a single line ending format at some >>>>> point, but it would be such a huge commit. >>>>> >>>>> On 12 April 2016 at 13:51, Gary Gregory <[email protected]> >>>>> wrote: >>>>> >>>>>> I'm so annoyed and apologize for this all lines changed commit. I >>>>>> only renamed a variable. >>>>>> >>>>>> Gary >>>>>> >>>>>> ---------- Forwarded message ---------- >>>>>> From: <[email protected]> >>>>>> Date: Tue, Apr 12, 2016 at 11:47 AM >>>>>> Subject: logging-log4j2 git commit: I always use "Millis" as the post >>>>>> fix to avoid any confusion. >>>>>> To: [email protected] >>>>>> >>>>>> >>>>>> Repository: logging-log4j2 >>>>>> Updated Branches: >>>>>> refs/heads/master c55ace781 -> eb32b2f77 >>>>>> >>>>>> >>>>>> I always use "Millis" as the post fix to avoid any confusion. >>>>>> >>>>>> Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo >>>>>> Commit: >>>>>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/eb32b2f7 >>>>>> Tree: >>>>>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/eb32b2f7 >>>>>> Diff: >>>>>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/eb32b2f7 >>>>>> >>>>>> Branch: refs/heads/master >>>>>> Commit: eb32b2f77634609a98c9940fac8e28b7e0d20f38 >>>>>> Parents: c55ace7 >>>>>> Author: ggregory <[email protected]> >>>>>> Authored: Tue Apr 12 11:47:03 2016 -0700 >>>>>> Committer: ggregory <[email protected]> >>>>>> Committed: Tue Apr 12 11:47:03 2016 -0700 >>>>>> >>>>>> ---------------------------------------------------------------------- >>>>>> .../logging/log4j/core/async/DisruptorUtil.java | 296 >>>>>> +++++++++---------- >>>>>> 1 file changed, 148 insertions(+), 148 deletions(-) >>>>>> ---------------------------------------------------------------------- >>>>>> >>>>>> >>>>>> >>>>>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/eb32b2f7/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java >>>>>> ---------------------------------------------------------------------- >>>>>> diff --git >>>>>> a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java >>>>>> b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java >>>>>> index 4faa174..3ce30f0 100644 >>>>>> --- >>>>>> a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java >>>>>> +++ >>>>>> b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/DisruptorUtil.java >>>>>> @@ -1,148 +1,148 @@ >>>>>> -/* >>>>>> - * 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.core.async; >>>>>> - >>>>>> -import java.util.concurrent.Callable; >>>>>> -import java.util.concurrent.ExecutorService; >>>>>> -import java.util.concurrent.Future; >>>>>> -import java.util.concurrent.TimeUnit; >>>>>> - >>>>>> -import com.lmax.disruptor.*; >>>>>> -import org.apache.logging.log4j.Logger; >>>>>> -import org.apache.logging.log4j.core.util.Constants; >>>>>> -import org.apache.logging.log4j.core.util.Integers; >>>>>> -import org.apache.logging.log4j.status.StatusLogger; >>>>>> -import org.apache.logging.log4j.util.LoaderUtil; >>>>>> -import org.apache.logging.log4j.util.PropertiesUtil; >>>>>> - >>>>>> -/** >>>>>> - * Utility methods for getting Disruptor related configuration. >>>>>> - */ >>>>>> -final class DisruptorUtil { >>>>>> - private static final Logger LOGGER = StatusLogger.getLogger(); >>>>>> - private static final int RINGBUFFER_MIN_SIZE = 128; >>>>>> - private static final int RINGBUFFER_DEFAULT_SIZE = 256 * 1024; >>>>>> - private static final int RINGBUFFER_NO_GC_DEFAULT_SIZE = 4 * >>>>>> 1024; >>>>>> - >>>>>> - private DisruptorUtil() { >>>>>> - } >>>>>> - >>>>>> - static long getTimeout(final String propertyName, final long >>>>>> defaultTimeout) { >>>>>> - return >>>>>> PropertiesUtil.getProperties().getLongProperty(propertyName, >>>>>> defaultTimeout); >>>>>> - } >>>>>> - >>>>>> - static WaitStrategy createWaitStrategy(final String >>>>>> propertyName) { >>>>>> - final String key = propertyName.startsWith("AsyncLogger.") >>>>>> - ? "AsyncLogger.Timeout" >>>>>> - : "AsyncLoggerConfig.Timeout"; >>>>>> - final long timeout = DisruptorUtil.getTimeout(key, 10L); >>>>>> - return createWaitStrategy(propertyName, timeout); >>>>>> - } >>>>>> - >>>>>> - static WaitStrategy createWaitStrategy(final String >>>>>> propertyName, final long timeoutMs) { >>>>>> - final String strategy = >>>>>> PropertiesUtil.getProperties().getStringProperty(propertyName); >>>>>> - if (strategy != null) { >>>>>> - LOGGER.trace("property {}={}", propertyName, strategy); >>>>>> - if ("Sleep".equalsIgnoreCase(strategy)) { >>>>>> - return new SleepingWaitStrategy(); >>>>>> - } else if ("Yield".equalsIgnoreCase(strategy)) { >>>>>> - return new YieldingWaitStrategy(); >>>>>> - } else if ("Block".equalsIgnoreCase(strategy)) { >>>>>> - return new BlockingWaitStrategy(); >>>>>> - } else if ("BusySpin".equalsIgnoreCase(strategy)) { >>>>>> - return new BusySpinWaitStrategy(); >>>>>> - } else if ("Timeout".equalsIgnoreCase(strategy)) { >>>>>> - return new TimeoutBlockingWaitStrategy(timeoutMs, >>>>>> TimeUnit.MILLISECONDS); >>>>>> - } >>>>>> - } >>>>>> - return new TimeoutBlockingWaitStrategy(timeoutMs, >>>>>> TimeUnit.MILLISECONDS); >>>>>> - } >>>>>> - >>>>>> - static int calculateRingBufferSize(final String propertyName) { >>>>>> - int ringBufferSize = Constants.ENABLE_THREADLOCALS ? >>>>>> RINGBUFFER_NO_GC_DEFAULT_SIZE : RINGBUFFER_DEFAULT_SIZE; >>>>>> - final String userPreferredRBSize = >>>>>> PropertiesUtil.getProperties().getStringProperty(propertyName, >>>>>> - String.valueOf(ringBufferSize)); >>>>>> - try { >>>>>> - int size = Integer.parseInt(userPreferredRBSize); >>>>>> - if (size < RINGBUFFER_MIN_SIZE) { >>>>>> - size = RINGBUFFER_MIN_SIZE; >>>>>> - LOGGER.warn("Invalid RingBufferSize {}, using >>>>>> minimum size {}.", userPreferredRBSize, >>>>>> - RINGBUFFER_MIN_SIZE); >>>>>> - } >>>>>> - ringBufferSize = size; >>>>>> - } catch (final Exception ex) { >>>>>> - LOGGER.warn("Invalid RingBufferSize {}, using default >>>>>> size {}.", userPreferredRBSize, ringBufferSize); >>>>>> - } >>>>>> - return Integers.ceilingNextPowerOfTwo(ringBufferSize); >>>>>> - } >>>>>> - >>>>>> - static ExceptionHandler<RingBufferLogEvent> >>>>>> getAsyncLoggerExceptionHandler() { >>>>>> - final String cls = >>>>>> PropertiesUtil.getProperties().getStringProperty("AsyncLogger.ExceptionHandler"); >>>>>> - if (cls == null) { >>>>>> - return new DefaultAsyncLoggerExceptionHandler(); >>>>>> - } >>>>>> - try { >>>>>> - @SuppressWarnings("unchecked") >>>>>> - final Class<? extends >>>>>> ExceptionHandler<RingBufferLogEvent>> klass = >>>>>> - (Class<? extends >>>>>> ExceptionHandler<RingBufferLogEvent>>) LoaderUtil.loadClass(cls); >>>>>> - return klass.newInstance(); >>>>>> - } catch (final Exception ignored) { >>>>>> - LOGGER.debug("Invalid AsyncLogger.ExceptionHandler >>>>>> value: error creating {}: ", cls, ignored); >>>>>> - return new DefaultAsyncLoggerExceptionHandler(); >>>>>> - } >>>>>> - } >>>>>> - >>>>>> - static >>>>>> ExceptionHandler<AsyncLoggerConfigDisruptor.Log4jEventWrapper> >>>>>> getAsyncLoggerConfigExceptionHandler() { >>>>>> - final String cls = >>>>>> PropertiesUtil.getProperties().getStringProperty("AsyncLoggerConfig.ExceptionHandler"); >>>>>> - if (cls == null) { >>>>>> - return new DefaultAsyncLoggerConfigExceptionHandler(); >>>>>> - } >>>>>> - try { >>>>>> - @SuppressWarnings("unchecked") >>>>>> - final Class<? extends >>>>>> ExceptionHandler<AsyncLoggerConfigDisruptor.Log4jEventWrapper>> klass = >>>>>> - (Class<? extends >>>>>> ExceptionHandler<AsyncLoggerConfigDisruptor.Log4jEventWrapper>>) >>>>>> LoaderUtil.loadClass(cls); >>>>>> - return klass.newInstance(); >>>>>> - } catch (final Exception ignored) { >>>>>> - LOGGER.debug("Invalid AsyncLoggerConfig.ExceptionHandler >>>>>> value: error creating {}: ", cls, ignored); >>>>>> - return new DefaultAsyncLoggerConfigExceptionHandler(); >>>>>> - } >>>>>> - } >>>>>> - >>>>>> - /** >>>>>> - * Returns the thread ID of the background appender thread. This >>>>>> allows us to detect Logger.log() calls initiated >>>>>> - * from the appender thread, which may cause deadlock when the >>>>>> RingBuffer is full. (LOG4J2-471) >>>>>> - * >>>>>> - * @param executor runs the appender thread >>>>>> - * @return the thread ID of the background appender thread >>>>>> - */ >>>>>> - public static long getExecutorThreadId(final ExecutorService >>>>>> executor) { >>>>>> - Future<Long> result = executor.submit(new Callable<Long>() { >>>>>> - @Override >>>>>> - public Long call() { >>>>>> - return Thread.currentThread().getId(); >>>>>> - } >>>>>> - }); >>>>>> - try { >>>>>> - return result.get(); >>>>>> - } catch (final Exception ex) { >>>>>> - final String msg = "Could not obtain executor thread Id. >>>>>> " >>>>>> - + "Giving up to avoid the risk of application >>>>>> deadlock."; >>>>>> - throw new IllegalStateException(msg, ex); >>>>>> - } >>>>>> - } >>>>>> -} >>>>>> +/* >>>>>> + * 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.core.async; >>>>>> + >>>>>> +import java.util.concurrent.Callable; >>>>>> +import java.util.concurrent.ExecutorService; >>>>>> +import java.util.concurrent.Future; >>>>>> +import java.util.concurrent.TimeUnit; >>>>>> + >>>>>> +import com.lmax.disruptor.*; >>>>>> +import org.apache.logging.log4j.Logger; >>>>>> +import org.apache.logging.log4j.core.util.Constants; >>>>>> +import org.apache.logging.log4j.core.util.Integers; >>>>>> +import org.apache.logging.log4j.status.StatusLogger; >>>>>> +import org.apache.logging.log4j.util.LoaderUtil; >>>>>> +import org.apache.logging.log4j.util.PropertiesUtil; >>>>>> + >>>>>> +/** >>>>>> + * Utility methods for getting Disruptor related configuration. >>>>>> + */ >>>>>> +final class DisruptorUtil { >>>>>> + private static final Logger LOGGER = StatusLogger.getLogger(); >>>>>> + private static final int RINGBUFFER_MIN_SIZE = 128; >>>>>> + private static final int RINGBUFFER_DEFAULT_SIZE = 256 * 1024; >>>>>> + private static final int RINGBUFFER_NO_GC_DEFAULT_SIZE = 4 * >>>>>> 1024; >>>>>> + >>>>>> + private DisruptorUtil() { >>>>>> + } >>>>>> + >>>>>> + static long getTimeout(final String propertyName, final long >>>>>> defaultTimeout) { >>>>>> + return >>>>>> PropertiesUtil.getProperties().getLongProperty(propertyName, >>>>>> defaultTimeout); >>>>>> + } >>>>>> + >>>>>> + static WaitStrategy createWaitStrategy(final String >>>>>> propertyName) { >>>>>> + final String key = propertyName.startsWith("AsyncLogger.") >>>>>> + ? "AsyncLogger.Timeout" >>>>>> + : "AsyncLoggerConfig.Timeout"; >>>>>> + final long timeout = DisruptorUtil.getTimeout(key, 10L); >>>>>> + return createWaitStrategy(propertyName, timeout); >>>>>> + } >>>>>> + >>>>>> + static WaitStrategy createWaitStrategy(final String >>>>>> propertyName, final long timeoutMillis) { >>>>>> + final String strategy = >>>>>> PropertiesUtil.getProperties().getStringProperty(propertyName); >>>>>> + if (strategy != null) { >>>>>> + LOGGER.trace("property {}={}", propertyName, strategy); >>>>>> + if ("Sleep".equalsIgnoreCase(strategy)) { >>>>>> + return new SleepingWaitStrategy(); >>>>>> + } else if ("Yield".equalsIgnoreCase(strategy)) { >>>>>> + return new YieldingWaitStrategy(); >>>>>> + } else if ("Block".equalsIgnoreCase(strategy)) { >>>>>> + return new BlockingWaitStrategy(); >>>>>> + } else if ("BusySpin".equalsIgnoreCase(strategy)) { >>>>>> + return new BusySpinWaitStrategy(); >>>>>> + } else if ("Timeout".equalsIgnoreCase(strategy)) { >>>>>> + return new >>>>>> TimeoutBlockingWaitStrategy(timeoutMillis, TimeUnit.MILLISECONDS); >>>>>> + } >>>>>> + } >>>>>> + return new TimeoutBlockingWaitStrategy(timeoutMillis, >>>>>> TimeUnit.MILLISECONDS); >>>>>> + } >>>>>> + >>>>>> + static int calculateRingBufferSize(final String propertyName) { >>>>>> + int ringBufferSize = Constants.ENABLE_THREADLOCALS ? >>>>>> RINGBUFFER_NO_GC_DEFAULT_SIZE : RINGBUFFER_DEFAULT_SIZE; >>>>>> + final String userPreferredRBSize = >>>>>> PropertiesUtil.getProperties().getStringProperty(propertyName, >>>>>> + String.valueOf(ringBufferSize)); >>>>>> + try { >>>>>> + int size = Integer.parseInt(userPreferredRBSize); >>>>>> + if (size < RINGBUFFER_MIN_SIZE) { >>>>>> + size = RINGBUFFER_MIN_SIZE; >>>>>> + LOGGER.warn("Invalid RingBufferSize {}, using >>>>>> minimum size {}.", userPreferredRBSize, >>>>>> + RINGBUFFER_MIN_SIZE); >>>>>> + } >>>>>> + ringBufferSize = size; >>>>>> + } catch (final Exception ex) { >>>>>> + LOGGER.warn("Invalid RingBufferSize {}, using default >>>>>> size {}.", userPreferredRBSize, ringBufferSize); >>>>>> + } >>>>>> + return Integers.ceilingNextPowerOfTwo(ringBufferSize); >>>>>> + } >>>>>> + >>>>>> + static ExceptionHandler<RingBufferLogEvent> >>>>>> getAsyncLoggerExceptionHandler() { >>>>>> + final String cls = >>>>>> PropertiesUtil.getProperties().getStringProperty("AsyncLogger.ExceptionHandler"); >>>>>> + if (cls == null) { >>>>>> + return new DefaultAsyncLoggerExceptionHandler(); >>>>>> + } >>>>>> + try { >>>>>> + @SuppressWarnings("unchecked") >>>>>> + final Class<? extends >>>>>> ExceptionHandler<RingBufferLogEvent>> klass = >>>>>> + (Class<? extends >>>>>> ExceptionHandler<RingBufferLogEvent>>) LoaderUtil.loadClass(cls); >>>>>> + return klass.newInstance(); >>>>>> + } catch (final Exception ignored) { >>>>>> + LOGGER.debug("Invalid AsyncLogger.ExceptionHandler >>>>>> value: error creating {}: ", cls, ignored); >>>>>> + return new DefaultAsyncLoggerExceptionHandler(); >>>>>> + } >>>>>> + } >>>>>> + >>>>>> + static >>>>>> ExceptionHandler<AsyncLoggerConfigDisruptor.Log4jEventWrapper> >>>>>> getAsyncLoggerConfigExceptionHandler() { >>>>>> + final String cls = >>>>>> PropertiesUtil.getProperties().getStringProperty("AsyncLoggerConfig.ExceptionHandler"); >>>>>> + if (cls == null) { >>>>>> + return new DefaultAsyncLoggerConfigExceptionHandler(); >>>>>> + } >>>>>> + try { >>>>>> + @SuppressWarnings("unchecked") >>>>>> + final Class<? extends >>>>>> ExceptionHandler<AsyncLoggerConfigDisruptor.Log4jEventWrapper>> klass = >>>>>> + (Class<? extends >>>>>> ExceptionHandler<AsyncLoggerConfigDisruptor.Log4jEventWrapper>>) >>>>>> LoaderUtil.loadClass(cls); >>>>>> + return klass.newInstance(); >>>>>> + } catch (final Exception ignored) { >>>>>> + LOGGER.debug("Invalid AsyncLoggerConfig.ExceptionHandler >>>>>> value: error creating {}: ", cls, ignored); >>>>>> + return new DefaultAsyncLoggerConfigExceptionHandler(); >>>>>> + } >>>>>> + } >>>>>> + >>>>>> + /** >>>>>> + * Returns the thread ID of the background appender thread. This >>>>>> allows us to detect Logger.log() calls initiated >>>>>> + * from the appender thread, which may cause deadlock when the >>>>>> RingBuffer is full. (LOG4J2-471) >>>>>> + * >>>>>> + * @param executor runs the appender thread >>>>>> + * @return the thread ID of the background appender thread >>>>>> + */ >>>>>> + public static long getExecutorThreadId(final ExecutorService >>>>>> executor) { >>>>>> + Future<Long> result = executor.submit(new Callable<Long>() { >>>>>> + @Override >>>>>> + public Long call() { >>>>>> + return Thread.currentThread().getId(); >>>>>> + } >>>>>> + }); >>>>>> + try { >>>>>> + return result.get(); >>>>>> + } catch (final Exception ex) { >>>>>> + final String msg = "Could not obtain executor thread Id. >>>>>> " >>>>>> + + "Giving up to avoid the risk of application >>>>>> deadlock."; >>>>>> + throw new IllegalStateException(msg, ex); >>>>>> + } >>>>>> + } >>>>>> +} >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> -- >>>>>> E-Mail: [email protected] | [email protected] >>>>>> Java Persistence with Hibernate, Second Edition >>>>>> <http://www.manning.com/bauer3/> >>>>>> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> >>>>>> Spring Batch in Action <http://www.manning.com/templier/> >>>>>> Blog: http://garygregory.wordpress.com >>>>>> Home: http://garygregory.com/ >>>>>> Tweet! http://twitter.com/GaryGregory >>>>>> >>>>> >>>>> >>>>> >>>>> -- >>>>> Matt Sicker <[email protected]> >>>>> >>>> >>>> >>>> >>>> -- >>>> E-Mail: [email protected] | [email protected] >>>> Java Persistence with Hibernate, Second Edition >>>> <http://www.manning.com/bauer3/> >>>> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> >>>> Spring Batch in Action <http://www.manning.com/templier/> >>>> Blog: http://garygregory.wordpress.com >>>> Home: http://garygregory.com/ >>>> Tweet! http://twitter.com/GaryGregory >>>> >>> >>> >>> >>> -- >>> Matt Sicker <[email protected]> >>> >> >> >> >> -- >> E-Mail: [email protected] | [email protected] >> Java Persistence with Hibernate, Second Edition >> <http://www.manning.com/bauer3/> >> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> >> Spring Batch in Action <http://www.manning.com/templier/> >> Blog: http://garygregory.wordpress.com >> Home: http://garygregory.com/ >> Tweet! http://twitter.com/GaryGregory >> >> >> > > > -- > E-Mail: [email protected] | [email protected] > Java Persistence with Hibernate, Second Edition > <http://www.manning.com/bauer3/> > JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> > Spring Batch in Action <http://www.manning.com/templier/> > Blog: http://garygregory.wordpress.com > Home: http://garygregory.com/ > Tweet! http://twitter.com/GaryGregory > -- Matt Sicker <[email protected]>
