From c97fb87ae8ed6bb9876feee17702ed3c4d26c66e Mon Sep 17 00:00:00 2001 From: Amol Nayak Date: Sun, 5 Feb 2012 00:12:37 +0530 Subject: [PATCH] INTSAMPLES-61 Changes, use LinkedHashMap to demonstrate LRU concept --- .../ftp/DynamicFtpChannelResolver.java | 42 ++++++++++++++++++- .../ftp/FtpOutboundChannelAdapterSample.java | 25 ++++++++++- pom.xml | 1 + 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/advanced/dynamic-ftp/src/main/java/org/springframework/integration/samples/ftp/DynamicFtpChannelResolver.java b/advanced/dynamic-ftp/src/main/java/org/springframework/integration/samples/ftp/DynamicFtpChannelResolver.java index 9a6ba2e6..889d435e 100644 --- a/advanced/dynamic-ftp/src/main/java/org/springframework/integration/samples/ftp/DynamicFtpChannelResolver.java +++ b/advanced/dynamic-ftp/src/main/java/org/springframework/integration/samples/ftp/DynamicFtpChannelResolver.java @@ -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. @@ -16,7 +16,9 @@ package org.springframework.integration.samples.ftp; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; +import java.util.Map.Entry; import java.util.Properties; import org.springframework.context.ConfigurableApplicationContext; @@ -30,12 +32,46 @@ import org.springframework.integration.MessageChannel; * to send files to dynamic destinations. * * @author Gary Russell + * @author Amol Nayak * @since 2.1 * */ public class DynamicFtpChannelResolver { - private final Map channels = new HashMap(); + //In production environment this value will be significantly higher + //This is just to demonstrate the concept of limiting the max number of + //Dynamically created application contexts we'll hold in memory when we execute + //the code from a junit + public static final int MAX_CACHE_SIZE = 2; + + private final LinkedHashMap channels = + new LinkedHashMap() { + + private static final long serialVersionUID = 1L; + + @Override + protected boolean removeEldestEntry( + Entry eldest) { + //This returning true means the least recently used + //channel and its application context will be closed and removed + boolean remove = size() > MAX_CACHE_SIZE; + if(remove) { + MessageChannel channel = eldest.getValue(); + ConfigurableApplicationContext ctx = contexts.get(channel); + if(ctx != null) { //shouldn't be null ideally + ctx.close(); + contexts.remove(channel); + } + } + return remove; + } + + }; + + private final Map contexts = + new HashMap(); + + /** * Resolve a customer to a channel, where each customer gets a private @@ -63,6 +99,8 @@ public class DynamicFtpChannelResolver { ctx.refresh(); channel = ctx.getBean("toFtpChannel", MessageChannel.class); this.channels.put(customer, channel); + //Will works as the same reference is presented always + this.contexts.put(channel, ctx); } return channel; } diff --git a/advanced/dynamic-ftp/src/test/java/org/springframework/integration/samples/ftp/FtpOutboundChannelAdapterSample.java b/advanced/dynamic-ftp/src/test/java/org/springframework/integration/samples/ftp/FtpOutboundChannelAdapterSample.java index 969a78aa..d19c0bf8 100644 --- a/advanced/dynamic-ftp/src/test/java/org/springframework/integration/samples/ftp/FtpOutboundChannelAdapterSample.java +++ b/advanced/dynamic-ftp/src/test/java/org/springframework/integration/samples/ftp/FtpOutboundChannelAdapterSample.java @@ -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. @@ -31,6 +31,7 @@ import org.springframework.integration.support.MessageBuilder; /** * @author Gary Russell + * @author Amol Nayak * */ public class FtpOutboundChannelAdapterSample { @@ -66,5 +67,27 @@ public class FtpOutboundChannelAdapterSample { assertTrue(e.getCause().getCause() instanceof UnknownHostException); assertEquals("host.for.cust2", e.getCause().getCause().getMessage()); } + + // send to a different customer; again, check the log to see a new ac is built + //and the first one created (cust1) should be closed and removed as per the max cache size restriction + message = MessageBuilder.withPayload(file) + .setHeader("customer", "cust3").build(); + try { + channel.send(message); + } catch (MessageHandlingException e) { + assertTrue(e.getCause().getCause() instanceof UnknownHostException); + assertEquals("host.for.cust3", e.getCause().getCause().getMessage()); + } + + //send to cust1 again, since this one has been invalidated before, we should + //see a new ac created (with ac of cust2 destroyed and removed) + message = MessageBuilder.withPayload(file) + .setHeader("customer", "cust1").build(); + try { + channel.send(message); + } catch (MessageHandlingException e) { + assertTrue(e.getCause().getCause() instanceof UnknownHostException); + assertEquals("host.for.cust1", e.getCause().getCause().getMessage()); + } } } diff --git a/pom.xml b/pom.xml index 725039fc..c1fcd6a1 100644 --- a/pom.xml +++ b/pom.xml @@ -13,6 +13,7 @@ basic intermediate + advanced applications