diff --git a/spring-integration-core/src/main/java/org/springframework/integration/core/MessageHeaders.java b/spring-integration-core/src/main/java/org/springframework/integration/core/MessageHeaders.java index 83d721ee5a..30ffa188fb 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/core/MessageHeaders.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/core/MessageHeaders.java @@ -77,7 +77,8 @@ public final class MessageHeaders implements Map, Serializable { public MessageHeaders(Map headers) { this.headers = (headers != null) ? new HashMap(headers) : new HashMap(); - this.headers.put(ID, TimeBasedUUIDGenerator.generateId()); + //this.headers.put(ID, TimeBasedUUIDGenerator.generateId()); + this.headers.put(ID, UUID.randomUUID()); this.headers.put(TIMESTAMP, new Long(System.currentTimeMillis())); if (this.headers.get(HISTORY) == null) { this.headers.put(HISTORY, new MessageHistory()); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/core/TimeBasedUUIDGenerator.java b/spring-integration-core/src/main/java/org/springframework/integration/core/TimeBasedUUIDGenerator.java index b24a41f0b3..3b6811f4c5 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/core/TimeBasedUUIDGenerator.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/core/TimeBasedUUIDGenerator.java @@ -15,8 +15,13 @@ */ package org.springframework.integration.core; +import java.net.InetAddress; +import java.net.NetworkInterface; import java.util.UUID; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + /** * Will generate time-based UUID (version 1 UUID). * This will allow Message ID to be unique but also contain an @@ -28,6 +33,27 @@ import java.util.UUID; class TimeBasedUUIDGenerator { public static final Object lock = new Object(); private static long lastTime; + private static final Log logger = LogFactory.getLog(TimeBasedUUIDGenerator.class); + private static long macAddressAsLong = 0; + + static { + try { + InetAddress address = InetAddress.getLocalHost(); + NetworkInterface ni = NetworkInterface.getByInetAddress(address); + if (ni != null) { + byte[] mac = ni.getHardwareAddress(); + //Converts array of unsigned bytes to an long + if (mac != null) { + for (int i = 0; i < mac.length; i++) { + macAddressAsLong |= mac[i] & 0xFF; + macAddressAsLong <<= 8; + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } /** * Will generate unique time based UUID where the next UUID is @@ -45,6 +71,7 @@ class TimeBasedUUIDGenerator { */ public final static UUID generateIdFromTimestamp(long currentTimeMillis){ long time; + long macNanoTime; synchronized (lock) { if (currentTimeMillis > lastTime) { lastTime = currentTimeMillis; @@ -63,7 +90,17 @@ class TimeBasedUUIDGenerator { // hi Time time |= 0x1000 | ((currentTimeMillis >> 48) & 0x0FFF); // version 1 - - return new UUID(time, System.nanoTime()); + + macNanoTime = macAddressAsLong; + if (macNanoTime == 0){ + logger.warn("Can not determine machine's MAC address. Will use System.nanoTime() for UUID generation, however there is a slim chance of it not being globally unique"); + macNanoTime = System.nanoTime(); + } else { + //considering the type of time returned by nanoTime, this will ensure that + // even if more then one process is running on the same machine, the id is still unique + macNanoTime |= System.nanoTime() & 0xFF; + macNanoTime <<= 8; + } + return new UUID(time, macNanoTime); } } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/core/TimeBasedUUIDGeneratorTests.java b/spring-integration-core/src/test/java/org/springframework/integration/core/TimeBasedUUIDGeneratorTests.java new file mode 100644 index 0000000000..4eb445c77e --- /dev/null +++ b/spring-integration-core/src/test/java/org/springframework/integration/core/TimeBasedUUIDGeneratorTests.java @@ -0,0 +1,50 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed 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.springframework.integration.core; + +import java.util.UUID; + +import org.junit.Assert; +import org.junit.Test; + +/** + * @author Oleg Zhurakousky + * + */ +public class TimeBasedUUIDGeneratorTests { + + @Test + public void testGreaterThen(){ + UUID id = TimeBasedUUIDGenerator.generateId(); + for (int i = 0; i < 1000; i++) { + UUID newId = TimeBasedUUIDGenerator.generateId(); + // tests, that newly created UUID is always greater then the previous one. + Assert.assertTrue(newId.compareTo(id) == 1); + id = newId; + } + } + @Test + public void testUniqueness(){ + long timestamp = System.currentTimeMillis(); + UUID id = TimeBasedUUIDGenerator.generateIdFromTimestamp(timestamp); + for (int i = 0; i < 1000; i++) { + UUID newId = TimeBasedUUIDGenerator.generateIdFromTimestamp(timestamp); + // tests, that newly created UUID is always greater then the previous one. + Assert.assertTrue(newId.compareTo(id) == 1); + id = newId; + } + } +}