INT-1141 Improve on how MessageHandlers are stored
INT-1141 polished code INT-1141 added tests INT-1141 improved how iterator is obtaind from OrderAwareLikedHashSet INT-1141 polishing INT-1141 stashed commit with List-based collection and performance tests INT-1141 improved OrderedAwareLinkedHashSet INT-1141 polishing INT-1141, INT-2627 improved LoadBalancingStrategy and RoundRobinLoadBalancingStrategy to obtain handler's iterator faster INT-1141 improved getHandlerIterator method to ensure that it only executes reordering logic if there are more then one handler INT-1141 simplified OrderedAwareLinkedHashSet to not to extend from LinkedHashSet INT-1141 changed OrderedAwareLinkedHashSet to OrderedAwareCopyOnWriteArraySetTests, imporoved array creation in RoundRobinLoadBalancingStrategy INT-1141 polished failing tests and RoundRobinLoadBalancingStrategy. Removed 'transient' from OrderedAwareCopyOnWriteArraySet
This commit is contained in:
committed by
Gary Russell
parent
7dd1255351
commit
2b49c66f64
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.integration.dispatcher;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
@@ -35,31 +32,32 @@ import org.springframework.util.Assert;
|
||||
* dispatching strategies may invoke handles in different ways (e.g. round-robin
|
||||
* vs. failover), this class does maintain the order of the underlying
|
||||
* collection. See the {@link OrderedAwareLinkedHashSet} for more detail.
|
||||
*
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Iwein Fuld
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @author Diego Belfer
|
||||
*/
|
||||
public abstract class AbstractDispatcher implements MessageDispatcher {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private final Set<MessageHandler> handlers = new OrderedAwareLinkedHashSet<MessageHandler>();
|
||||
private final OrderedAwareCopyOnWriteArraySet<MessageHandler> handlers =
|
||||
new OrderedAwareCopyOnWriteArraySet<MessageHandler>();
|
||||
|
||||
|
||||
/**
|
||||
* Returns a copied, unmodifiable List of this dispatcher's handlers. This
|
||||
* Returns an unmodifiable {@link Set} of this dispatcher's handlers. This
|
||||
* is provided for access by subclasses.
|
||||
*/
|
||||
protected List<MessageHandler> getHandlers() {
|
||||
return Collections.<MessageHandler>unmodifiableList(Arrays.<MessageHandler>asList(
|
||||
this.handlers.toArray(new MessageHandler[this.handlers.size()])));
|
||||
protected Set<MessageHandler> getHandlers() {
|
||||
return handlers.asUnmodifiableSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the handler to the internal Set.
|
||||
*
|
||||
*
|
||||
* @return the result of {@link Set#add(Object)}
|
||||
*/
|
||||
public boolean addHandler(MessageHandler handler) {
|
||||
@@ -69,7 +67,7 @@ public abstract class AbstractDispatcher implements MessageDispatcher {
|
||||
|
||||
/**
|
||||
* Remove the handler from the internal handler Set.
|
||||
*
|
||||
*
|
||||
* @return the result of {@link Set#remove(Object)}
|
||||
*/
|
||||
public boolean removeHandler(MessageHandler handler) {
|
||||
@@ -77,6 +75,7 @@ public abstract class AbstractDispatcher implements MessageDispatcher {
|
||||
return this.handlers.remove(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getSimpleName() + " with handlers: " + this.handlers.toString();
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.integration.dispatcher;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
@@ -34,10 +34,11 @@ import org.springframework.integration.support.MessageBuilder;
|
||||
* If the 'ignoreFailures' flag is set to <code>true</code> on the other hand, it will make a best effort to send the
|
||||
* message to each of its handlers. In other words, when 'ignoreFailures' is <code>true</code>, if it fails to send to
|
||||
* any one handler, it will simply log a warn-level message but continue to send the Message to any other handlers.
|
||||
*
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Iwein Fuld
|
||||
* @author Gary Russell
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
public class BroadcastingDispatcher extends AbstractDispatcher {
|
||||
|
||||
@@ -91,7 +92,7 @@ public class BroadcastingDispatcher extends AbstractDispatcher {
|
||||
public boolean dispatch(Message<?> message) {
|
||||
boolean dispatched = false;
|
||||
int sequenceNumber = 1;
|
||||
List<MessageHandler> handlers = this.getHandlers();
|
||||
Collection<MessageHandler> handlers = this.getHandlers();
|
||||
if (this.requireSubscribers && handlers.size() == 0) {
|
||||
throw new MessageDispatchingException(message, "Dispatcher has no subscribers");
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2002-2009 the original author or authors.
|
||||
/* Copyright 2002-2012 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.
|
||||
@@ -15,20 +15,21 @@
|
||||
|
||||
package org.springframework.integration.dispatcher;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
|
||||
/**
|
||||
* Strategy for determining the iteration order of a MessageHandler list.
|
||||
*
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 1.0.3
|
||||
*/
|
||||
public interface LoadBalancingStrategy {
|
||||
|
||||
public Iterator<MessageHandler> getHandlerIterator(Message<?> message, List<MessageHandler> handlers);
|
||||
public Iterator<MessageHandler> getHandlerIterator(Message<?> message, Collection<MessageHandler> handlers);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -17,9 +17,12 @@
|
||||
package org.springframework.integration.dispatcher;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
||||
@@ -34,23 +37,24 @@ import org.springframework.util.StringUtils;
|
||||
/**
|
||||
* Special Set that maintains the following semantics:
|
||||
* All elements that are un-ordered (do not implement {@link Ordered} interface or annotated
|
||||
* {@link Order} annotation) will be stored in the order in which they were added, maintaining the
|
||||
* semantics of the {@link LinkedHashSet}. However, for all {@link Ordered} elements a
|
||||
* {@link Order} annotation) will be stored in the order in which they were added.
|
||||
* However, for all {@link Ordered} elements a
|
||||
* {@link Comparator} (instantiated by default) for this implementation of {@link Set}, will be
|
||||
* used. Those elements will have precedence over un-ordered elements. If elements have the same
|
||||
* order but themselves do not equal to one another the more recent addition will be placed to the
|
||||
* right of (appended next to) the existing element with the same order, thus preserving the order
|
||||
* of the insertion and maintaining {@link LinkedHashSet} semantics for the un-ordered elements.
|
||||
* of the insertion while maintaining the order of insertion for the un-ordered elements.
|
||||
* <p>
|
||||
* The class is package-protected and only intended for use by the AbstractDispatcher. It
|
||||
* <emphasis>must</emphasis> enforce safe concurrent access for all usage by the dispatcher.
|
||||
*
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Mark Fisher
|
||||
* @author Diego Belfer
|
||||
* @since 1.0.3
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "serial"})
|
||||
class OrderedAwareLinkedHashSet<E> extends LinkedHashSet<E> {
|
||||
@SuppressWarnings({"unchecked"})
|
||||
class OrderedAwareCopyOnWriteArraySet<E> implements Set<E> {
|
||||
|
||||
private final OrderComparator comparator = new OrderComparator();
|
||||
|
||||
@@ -60,6 +64,19 @@ class OrderedAwareLinkedHashSet<E> extends LinkedHashSet<E> {
|
||||
|
||||
private final WriteLock writeLock = rwl.writeLock();
|
||||
|
||||
private final CopyOnWriteArraySet<E> elements;
|
||||
|
||||
private final Set<E> unmodifiableElements;
|
||||
|
||||
public OrderedAwareCopyOnWriteArraySet() {
|
||||
elements = new CopyOnWriteArraySet<E>();
|
||||
unmodifiableElements = Collections.unmodifiableSet(elements);
|
||||
}
|
||||
|
||||
public Set<E> asUnmodifiableSet() {
|
||||
return unmodifiableElements;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Every time an Ordered element is added via this method this
|
||||
@@ -69,19 +86,19 @@ class OrderedAwareLinkedHashSet<E> extends LinkedHashSet<E> {
|
||||
public boolean add(E o) {
|
||||
Assert.notNull(o,"Can not add NULL object");
|
||||
writeLock.lock();
|
||||
try {
|
||||
try {
|
||||
boolean present = false;
|
||||
if (o instanceof Ordered){
|
||||
present = this.addOrderedElement((Ordered) o);
|
||||
}
|
||||
else {
|
||||
present = super.add(o);
|
||||
present = elements.add(o);
|
||||
}
|
||||
return present;
|
||||
}
|
||||
finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,9 +108,9 @@ class OrderedAwareLinkedHashSet<E> extends LinkedHashSet<E> {
|
||||
Assert.notNull(c,"Can not merge with NULL set");
|
||||
writeLock.lock();
|
||||
try {
|
||||
for (E object : c) {
|
||||
for (E object : c) {
|
||||
this.add(object);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
finally {
|
||||
@@ -102,12 +119,14 @@ class OrderedAwareLinkedHashSet<E> extends LinkedHashSet<E> {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean remove(Object o) {
|
||||
writeLock.lock();
|
||||
try {
|
||||
return super.remove(o);
|
||||
boolean removed = elements.remove(o);
|
||||
//unmodifiableElements = Collections.unmodifiableSet(this);
|
||||
return removed;
|
||||
}
|
||||
finally {
|
||||
writeLock.unlock();
|
||||
@@ -115,7 +134,7 @@ class OrderedAwareLinkedHashSet<E> extends LinkedHashSet<E> {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean removeAll(Collection<?> c){
|
||||
if (CollectionUtils.isEmpty(c)){
|
||||
@@ -123,18 +142,17 @@ class OrderedAwareLinkedHashSet<E> extends LinkedHashSet<E> {
|
||||
}
|
||||
writeLock.lock();
|
||||
try {
|
||||
return super.removeAll(c);
|
||||
return elements.removeAll(c);
|
||||
}
|
||||
finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T[] toArray(T[] a) {
|
||||
readLock.lock();
|
||||
try {
|
||||
return super.toArray(a);
|
||||
return elements.toArray(a);
|
||||
}
|
||||
finally {
|
||||
readLock.unlock();
|
||||
@@ -145,7 +163,7 @@ class OrderedAwareLinkedHashSet<E> extends LinkedHashSet<E> {
|
||||
public String toString() {
|
||||
readLock.lock();
|
||||
try {
|
||||
return StringUtils.collectionToCommaDelimitedString(this);
|
||||
return StringUtils.collectionToCommaDelimitedString(elements);
|
||||
}
|
||||
finally {
|
||||
readLock.unlock();
|
||||
@@ -153,27 +171,27 @@ class OrderedAwareLinkedHashSet<E> extends LinkedHashSet<E> {
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private boolean addOrderedElement(Ordered adding) {
|
||||
private boolean addOrderedElement(Ordered adding) {
|
||||
boolean added = false;
|
||||
E[] tempUnorderedElements = (E[]) this.toArray();
|
||||
if (super.contains(adding)) {
|
||||
E[] tempUnorderedElements = (E[]) elements.toArray();
|
||||
if (elements.contains(adding)) {
|
||||
return false;
|
||||
}
|
||||
super.clear();
|
||||
elements.clear();
|
||||
|
||||
if (tempUnorderedElements.length == 0) {
|
||||
added = super.add((E) adding);
|
||||
added = elements.add((E) adding);
|
||||
}
|
||||
else {
|
||||
Set tempSet = new LinkedHashSet();
|
||||
for (E current : tempUnorderedElements) {
|
||||
if (current instanceof Ordered) {
|
||||
if (this.comparator.compare(adding, current) < 0) {
|
||||
added = super.add((E) adding);
|
||||
super.add(current);
|
||||
added = elements.add((E) adding);
|
||||
elements.add(current);
|
||||
}
|
||||
else {
|
||||
super.add(current);
|
||||
elements.add(current);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -181,13 +199,44 @@ class OrderedAwareLinkedHashSet<E> extends LinkedHashSet<E> {
|
||||
}
|
||||
}
|
||||
if (!added) {
|
||||
added = super.add((E) adding);
|
||||
added = elements.add((E) adding);
|
||||
}
|
||||
for (Object object : tempSet) {
|
||||
super.add((E) object);
|
||||
elements.add((E) object);
|
||||
}
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return this.elements.iterator();
|
||||
}
|
||||
|
||||
public int size(){
|
||||
return this.elements.size();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.elements.isEmpty();
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
return this.elements.contains(o);
|
||||
}
|
||||
|
||||
public Object[] toArray() {
|
||||
return this.elements.toArray();
|
||||
}
|
||||
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
return this.elements.containsAll(c);
|
||||
}
|
||||
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
return this.elements.retainAll(c);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.elements.clear();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -16,9 +16,8 @@
|
||||
|
||||
package org.springframework.integration.dispatcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
@@ -28,32 +27,56 @@ import org.springframework.integration.core.MessageHandler;
|
||||
* Round-robin implementation of {@link LoadBalancingStrategy}. This
|
||||
* implementation will keep track of the index of the handler that has been
|
||||
* tried first and use a different starting handler every dispatch.
|
||||
*
|
||||
*
|
||||
* @author Iwein Fuld
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 1.0.3
|
||||
*/
|
||||
public class RoundRobinLoadBalancingStrategy implements LoadBalancingStrategy {
|
||||
|
||||
private final AtomicInteger currentHandlerIndex = new AtomicInteger();
|
||||
|
||||
|
||||
/**
|
||||
* Returns an iterator that starts at a new point in the list every time the
|
||||
* Returns an iterator that starts at a new point in the collection every time the
|
||||
* first part of the list that is skipped will be used at the end of the
|
||||
* iteration, so it guarantees all handlers are returned once on subsequent
|
||||
* <code>next()</code> invocations.
|
||||
*/
|
||||
public final Iterator<MessageHandler> getHandlerIterator(final Message<?> message, final List<MessageHandler> handlers) {
|
||||
public final Iterator<MessageHandler> getHandlerIterator(final Message<?> message, final Collection<MessageHandler> handlers) {
|
||||
int size = handlers.size();
|
||||
if (size == 0) {
|
||||
if (size < 2) {
|
||||
this.getNextHandlerStartIndex(size);
|
||||
return handlers.iterator();
|
||||
}
|
||||
|
||||
return this.buildHandlerIterator(size, handlers.toArray(new MessageHandler[size]));
|
||||
}
|
||||
|
||||
private Iterator<MessageHandler> buildHandlerIterator(int size, final MessageHandler[] handlers){
|
||||
|
||||
int nextHandlerStartIndex = getNextHandlerStartIndex(size);
|
||||
List<MessageHandler> reorderedHandlers = new ArrayList<MessageHandler>(
|
||||
handlers.subList(nextHandlerStartIndex, size));
|
||||
reorderedHandlers.addAll(handlers.subList(0, nextHandlerStartIndex));
|
||||
return reorderedHandlers.iterator();
|
||||
|
||||
final MessageHandler[] reorderedHandlers = new MessageHandler[size];
|
||||
|
||||
System.arraycopy(handlers, nextHandlerStartIndex, reorderedHandlers, 0, size-nextHandlerStartIndex);
|
||||
System.arraycopy(handlers, 0, reorderedHandlers, size-nextHandlerStartIndex, 0+nextHandlerStartIndex);
|
||||
|
||||
return new Iterator<MessageHandler>() {
|
||||
int currentIndex = 0;
|
||||
|
||||
public boolean hasNext() {
|
||||
return currentIndex < reorderedHandlers.length;
|
||||
}
|
||||
|
||||
public MessageHandler next() {
|
||||
return reorderedHandlers[currentIndex++];
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("Remove is not supported by this Iterator");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,8 +85,12 @@ public class RoundRobinLoadBalancingStrategy implements LoadBalancingStrategy {
|
||||
* <code>size</code>.
|
||||
*/
|
||||
private int getNextHandlerStartIndex(int size) {
|
||||
int indexTail = currentHandlerIndex.getAndIncrement() % size;
|
||||
return indexTail < 0 ? indexTail + size : indexTail;
|
||||
if (size > 0){
|
||||
int indexTail = currentHandlerIndex.getAndIncrement() % size;
|
||||
return indexTail < 0 ? indexTail + size : indexTail;
|
||||
}
|
||||
else {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ import org.springframework.integration.core.MessageHandler;
|
||||
* <p/>
|
||||
* A load-balancing strategy may be provided to this class to control the order in
|
||||
* which the handlers will be tried.
|
||||
*
|
||||
*
|
||||
* @author Iwein Fuld
|
||||
* @author Mark Fisher
|
||||
* @author Gary Russell
|
||||
@@ -52,7 +52,7 @@ import org.springframework.integration.core.MessageHandler;
|
||||
public class UnicastingDispatcher extends AbstractDispatcher {
|
||||
|
||||
private volatile boolean failover = true;
|
||||
private ReadWriteLock rwLock = new ReentrantReadWriteLock();
|
||||
private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
|
||||
private volatile LoadBalancingStrategy loadBalancingStrategy;
|
||||
|
||||
private final Executor executor;
|
||||
@@ -84,7 +84,7 @@ public class UnicastingDispatcher extends AbstractDispatcher {
|
||||
lock.lock();
|
||||
try {
|
||||
this.loadBalancingStrategy = loadBalancingStrategy;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
lock.unlock();
|
||||
}
|
||||
@@ -145,7 +145,7 @@ public class UnicastingDispatcher extends AbstractDispatcher {
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
return this.getHandlers().iterator();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,20 +16,21 @@
|
||||
|
||||
package org.springframework.integration.dispatcher;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 1.0.3
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class OrderedAwareLinkedHashSetTests {
|
||||
public class OrderedAwareCopyOnWriteArraySetTests {
|
||||
|
||||
/**
|
||||
* Tests that semantics of the LinkedHashSet were not broken
|
||||
@@ -37,7 +38,7 @@ public class OrderedAwareLinkedHashSetTests {
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Test
|
||||
public void testAddUnordered(){
|
||||
OrderedAwareLinkedHashSet setToTest = new OrderedAwareLinkedHashSet();
|
||||
OrderedAwareCopyOnWriteArraySet setToTest = new OrderedAwareCopyOnWriteArraySet();
|
||||
setToTest.add("foo");
|
||||
setToTest.add("bar");
|
||||
setToTest.add("baz");
|
||||
@@ -49,16 +50,16 @@ public class OrderedAwareLinkedHashSetTests {
|
||||
}
|
||||
/**
|
||||
* Tests that semantics of TreeSet(Comparator) were not broken.
|
||||
* However, there is a special Comparator (instantiated by default) for this implementation of Set,
|
||||
* However, there is a special Comparator (instantiated by default) for this implementation of Set,
|
||||
* which allows elements with the same "order" as long as these elements themselves are not equal.
|
||||
* In this case element with the same order will be placed to the right (appended next to) of
|
||||
* the already existing element, thus preserving the order of insertion (LinkedHashset semantics)
|
||||
* within the elements that have the same "order" value.
|
||||
* In this case element with the same order will be placed to the right (appended next to) of
|
||||
* the already existing element, thus preserving the order of insertion (LinkedHashset semantics)
|
||||
* within the elements that have the same "order" value.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Test
|
||||
public void testAddOrdered(){
|
||||
OrderedAwareLinkedHashSet setToTest = new OrderedAwareLinkedHashSet();
|
||||
OrderedAwareCopyOnWriteArraySet setToTest = new OrderedAwareCopyOnWriteArraySet();
|
||||
Object o1 = new Foo(3);
|
||||
Object o2 = new Foo(1);
|
||||
Object o3 = new Foo(2);
|
||||
@@ -78,7 +79,7 @@ public class OrderedAwareLinkedHashSetTests {
|
||||
setToTest.add(o7);
|
||||
setToTest.add(o8);
|
||||
setToTest.add(o9);
|
||||
setToTest.add(o10);
|
||||
setToTest.add(o10);
|
||||
assertEquals(10, setToTest.size());
|
||||
Object[] elements = setToTest.toArray();
|
||||
assertEquals(o7, elements[0]);
|
||||
@@ -92,7 +93,7 @@ public class OrderedAwareLinkedHashSetTests {
|
||||
assertEquals(o5, elements[8]);
|
||||
assertEquals(o6, elements[9]);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Test
|
||||
public void testAddAllOrderedUnordered(){
|
||||
@@ -116,9 +117,9 @@ public class OrderedAwareLinkedHashSetTests {
|
||||
tempList.add(o7);
|
||||
tempList.add(o8);
|
||||
tempList.add(o9);
|
||||
tempList.add(o10);
|
||||
tempList.add(o10);
|
||||
assertEquals(10, tempList.size());
|
||||
OrderedAwareLinkedHashSet orderAwareSet = new OrderedAwareLinkedHashSet();
|
||||
OrderedAwareCopyOnWriteArraySet orderAwareSet = new OrderedAwareCopyOnWriteArraySet();
|
||||
orderAwareSet.addAll(tempList);
|
||||
Object[] elements = orderAwareSet.toArray();
|
||||
assertEquals(o7, elements[0]);
|
||||
@@ -132,7 +133,7 @@ public class OrderedAwareLinkedHashSetTests {
|
||||
assertEquals(o3, elements[8]);
|
||||
assertEquals(o10, elements[9]);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testConcurrent(){
|
||||
for(int i = 0; i < 1000; i++){
|
||||
@@ -141,7 +142,7 @@ public class OrderedAwareLinkedHashSetTests {
|
||||
}
|
||||
@SuppressWarnings("rawtypes")
|
||||
private void doConcurrent(){
|
||||
final OrderedAwareLinkedHashSet setToTest = new OrderedAwareLinkedHashSet();
|
||||
final OrderedAwareCopyOnWriteArraySet setToTest = new OrderedAwareCopyOnWriteArraySet();
|
||||
final Object o1 = new Foo(3);
|
||||
final Object o2 = new Foo(1);
|
||||
final Object o3 = new Foo(2);
|
||||
@@ -163,20 +164,20 @@ public class OrderedAwareLinkedHashSetTests {
|
||||
});
|
||||
Thread t2 = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
setToTest.add(o2);
|
||||
setToTest.add(o4);
|
||||
setToTest.add(o6);
|
||||
setToTest.add(o8);
|
||||
setToTest.add(o10);
|
||||
setToTest.add(o2);
|
||||
setToTest.add(o4);
|
||||
setToTest.add(o6);
|
||||
setToTest.add(o8);
|
||||
setToTest.add(o10);
|
||||
}
|
||||
});
|
||||
Thread t3 = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
setToTest.add(1);
|
||||
setToTest.add(new Foo(2));
|
||||
setToTest.add(3);
|
||||
setToTest.add(new Foo(9));
|
||||
setToTest.add(8);
|
||||
setToTest.add(1);
|
||||
setToTest.add(new Foo(2));
|
||||
setToTest.add(3);
|
||||
setToTest.add(new Foo(9));
|
||||
setToTest.add(8);
|
||||
}
|
||||
});
|
||||
t1.start();
|
||||
@@ -190,8 +191,8 @@ public class OrderedAwareLinkedHashSetTests {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
assertEquals(15, setToTest.size());
|
||||
}
|
||||
/**
|
||||
@@ -216,7 +217,7 @@ public class OrderedAwareLinkedHashSetTests {
|
||||
Object o8 = new Foo(Ordered.HIGHEST_PRECEDENCE);
|
||||
Object o9 = new Foo(4);
|
||||
Object o10 = "Baz";
|
||||
|
||||
|
||||
tempList.add(o1);
|
||||
tempList.add(o2);
|
||||
tempList.add(o3);
|
||||
@@ -226,8 +227,8 @@ public class OrderedAwareLinkedHashSetTests {
|
||||
tempList.add(o7);
|
||||
tempList.add(o8);
|
||||
tempList.add(o9);
|
||||
tempList.add(o10);
|
||||
final OrderedAwareLinkedHashSet orderAwareSet = new OrderedAwareLinkedHashSet();
|
||||
tempList.add(o10);
|
||||
final OrderedAwareCopyOnWriteArraySet orderAwareSet = new OrderedAwareCopyOnWriteArraySet();
|
||||
Thread t1 = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
orderAwareSet.addAll(tempList);
|
||||
@@ -256,9 +257,9 @@ public class OrderedAwareLinkedHashSetTests {
|
||||
Thread t3 = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
orderAwareSet.add("hello");
|
||||
orderAwareSet.add("hello again");
|
||||
orderAwareSet.add("hello again");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
t1.start();
|
||||
t2.start();
|
||||
@@ -275,13 +276,14 @@ public class OrderedAwareLinkedHashSetTests {
|
||||
assertEquals(18, elements.length);
|
||||
}
|
||||
private static class Foo implements Ordered {
|
||||
private int order;
|
||||
private final int order;
|
||||
public Foo(int order){
|
||||
this.order = order;
|
||||
}
|
||||
public int getOrder() {
|
||||
return order;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String toString(){
|
||||
return "Foo-" + order;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -47,7 +47,7 @@ public class FtpOutboundChannelAdapterParserTests {
|
||||
|
||||
@Test
|
||||
public void testFtpOutboundChannelAdapterComplete() throws Exception{
|
||||
ApplicationContext ac =
|
||||
ApplicationContext ac =
|
||||
new ClassPathXmlApplicationContext("FtpOutboundChannelAdapterParserTests-context.xml", this.getClass());
|
||||
Object consumer = ac.getBean("ftpOutbound");
|
||||
assertTrue(consumer instanceof EventDrivenConsumer);
|
||||
@@ -70,7 +70,7 @@ public class FtpOutboundChannelAdapterParserTests {
|
||||
assertEquals("localhost", TestUtils.getPropertyValue(sessionFactory, "host"));
|
||||
assertEquals(22, TestUtils.getPropertyValue(sessionFactory, "port"));
|
||||
assertEquals(23, TestUtils.getPropertyValue(handler, "order"));
|
||||
//verify subscription order
|
||||
//verify subscription order
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<MessageHandler> handlers = (Set<MessageHandler>) TestUtils
|
||||
.getPropertyValue(
|
||||
@@ -80,7 +80,7 @@ public class FtpOutboundChannelAdapterParserTests {
|
||||
assertSame(TestUtils.getPropertyValue(ac.getBean("ftpOutbound2"), "handler"), iterator.next());
|
||||
assertSame(handler, iterator.next());
|
||||
}
|
||||
|
||||
|
||||
@Test(expected=BeanCreationException.class)
|
||||
public void testFailWithEmptyRfsAndAcdTrue() throws Exception{
|
||||
new ClassPathXmlApplicationContext("FtpOutboundChannelAdapterParserTests-fail.xml", this.getClass());
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
@@ -65,6 +66,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*/
|
||||
@ContextConfiguration
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -19,7 +19,6 @@ package org.springframework.integration.sftp.config;
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
@@ -53,7 +52,7 @@ public class OutboundChannelAdapterParserTests {
|
||||
|
||||
@Test
|
||||
public void testOutboundChannelAdapterWithId(){
|
||||
ApplicationContext context =
|
||||
ApplicationContext context =
|
||||
new ClassPathXmlApplicationContext("OutboundChannelAdapterParserTests-context.xml", this.getClass());
|
||||
Object consumer = context.getBean("sftpOutboundAdapter");
|
||||
assertTrue(consumer instanceof EventDrivenConsumer);
|
||||
@@ -90,7 +89,7 @@ public class OutboundChannelAdapterParserTests {
|
||||
|
||||
@Test
|
||||
public void testOutboundChannelAdapterWithWithRemoteDirectoryAndFileExpression(){
|
||||
ApplicationContext context =
|
||||
ApplicationContext context =
|
||||
new ClassPathXmlApplicationContext("OutboundChannelAdapterParserTests-context.xml", this.getClass());
|
||||
Object consumer = context.getBean("sftpOutboundAdapterWithExpression");
|
||||
assertTrue(consumer instanceof EventDrivenConsumer);
|
||||
@@ -106,9 +105,9 @@ public class OutboundChannelAdapterParserTests {
|
||||
assertEquals("UTF-8", TestUtils.getPropertyValue(handler, "charset"));
|
||||
assertNotNull(TestUtils.getPropertyValue(handler, "temporaryDirectory"));
|
||||
assertNull(TestUtils.getPropertyValue(handler, "temporaryDirectoryExpressionProcessor"));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testOutboundChannelAdapterWithNoTemporaryFileName(){
|
||||
ApplicationContext context =
|
||||
@@ -121,12 +120,12 @@ public class OutboundChannelAdapterParserTests {
|
||||
@Test(expected=BeanDefinitionStoreException.class)
|
||||
public void testFailWithRemoteDirAndExpression(){
|
||||
new ClassPathXmlApplicationContext("OutboundChannelAdapterParserTests-context-fail.xml", this.getClass());
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test(expected=BeanDefinitionStoreException.class)
|
||||
public void testFailWithFileExpressionAndFileGenerator(){
|
||||
new ClassPathXmlApplicationContext("OutboundChannelAdapterParserTests-context-fail-fileFileGen.xml", this.getClass());
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ package org.springframework.integration.test.support;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.springframework.integration.test.matcher.HeaderMatcher.hasHeader;
|
||||
import static org.springframework.integration.test.matcher.PayloadMatcher.hasPayload;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -26,27 +28,24 @@ import org.springframework.integration.Message;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
import static org.springframework.integration.test.matcher.PayloadMatcher.hasPayload;
|
||||
import static org.springframework.integration.test.matcher.HeaderMatcher.hasHeader;
|
||||
|
||||
@ContextConfiguration
|
||||
@ContextConfiguration
|
||||
public class MessageScenariosTests extends AbstractRequestResponseScenarioTests {
|
||||
|
||||
|
||||
@Override
|
||||
protected List<RequestResponseScenario> defineRequestResponseScenarios() {
|
||||
List<RequestResponseScenario> scenarios= new ArrayList<RequestResponseScenario>();
|
||||
RequestResponseScenario scenario1 = new RequestResponseScenario(
|
||||
"inputChannel","outputChannel")
|
||||
.setPayload("hello")
|
||||
.setResponseValidator(new PayloadValidator<String>() {
|
||||
.setResponseValidator(new PayloadValidator<String>() {
|
||||
@Override
|
||||
protected void validateResponse(String response) {
|
||||
assertEquals("HELLO",response);
|
||||
}
|
||||
});
|
||||
|
||||
scenarios.add(scenario1);
|
||||
|
||||
|
||||
scenarios.add(scenario1);
|
||||
|
||||
RequestResponseScenario scenario2 = new RequestResponseScenario(
|
||||
"inputChannel","outputChannel")
|
||||
.setMessage(MessageBuilder.withPayload("hello").setHeader("foo", "bar").build())
|
||||
@@ -55,11 +54,11 @@ public class MessageScenariosTests extends AbstractRequestResponseScenarioTests
|
||||
protected void validateMessage(Message<?> message) {
|
||||
assertThat(message,hasPayload("HELLO"));
|
||||
assertThat(message,hasHeader("foo","bar"));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
scenarios.add(scenario2);
|
||||
|
||||
|
||||
scenarios.add(scenario2);
|
||||
|
||||
RequestResponseScenario scenario3 = new RequestResponseScenario(
|
||||
"inputChannel2","outputChannel2")
|
||||
.setMessage(MessageBuilder.withPayload("hello").setHeader("foo", "bar").build())
|
||||
@@ -68,11 +67,11 @@ public class MessageScenariosTests extends AbstractRequestResponseScenarioTests
|
||||
protected void validateMessage(Message<?> message) {
|
||||
assertThat(message,hasPayload("HELLO"));
|
||||
assertThat(message,hasHeader("foo","bar"));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
scenarios.add(scenario3);
|
||||
|
||||
|
||||
scenarios.add(scenario3);
|
||||
|
||||
return scenarios;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -56,7 +56,7 @@ public class PresenceOutboundChannelAdapterParserTests {
|
||||
.getPropertyValue(pollingConsumer, "handler");
|
||||
assertEquals(23, TestUtils.getPropertyValue(handler, "order"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRosterEventOutboundChannelAdapterParserEventConsumer(){
|
||||
Object eventConsumer = context.getBean("eventOutboundRosterAdapter");
|
||||
@@ -65,7 +65,7 @@ public class PresenceOutboundChannelAdapterParserTests {
|
||||
.getPropertyValue(eventConsumer, "handler");
|
||||
assertEquals(34, TestUtils.getPropertyValue(handler, "order"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRosterEventOutboundChannel(){
|
||||
Object channel = context.getBean("eventOutboundRosterChannel");
|
||||
|
||||
Reference in New Issue
Block a user