Friday, September 2, 2011

File Copy Using Java -- Basic and Fastest Way

Recently I had faced with situation to write simple copy command in Java, so I written the same using the plain old style and give it back to developer to implement and unit test the same. To my surprise developer comes back and reported me that my copy code is performing badly. Reason he want to use my copy code to copy at least 20 GB of file data.

So now I was faced with challenge to implement the fastest copy code. The first thing came to my mind was to use the nio API of java.

Copy using the java mainly depends on the following factors which you can control:

1) Buffer Size
2) Reading the data in efficient manner.

Buffer Size:

Buffer size is mainly dependent on operating system block size and CPU Cache. Example windows default block size is 4K (4096 Bytes).

Now if some one configure the block size of say 4500 bytes then two blocks (2* 4096) will be read and put it into the memory. So it means you had read extra bytes which will not be used and you pay the price for disk to ram read. Many times OS cache the blocks you read so next read it will be used but again here you pay the price of RAM and cost of RAM to CPU Cache copy. So ideally the buffer size should be equal to the block size or multiple of it ,so that every time you read it will be full block size read and there is no wastage. Remember cost of RAM to CPU Cache is much lesser than the cost of disk to RAM reads.

Again it depends on the CPU how it moves the data between L3 to L2 cache and complexity increases. So if you run your program under different cache size it gives different result. As per my experience the best buffer size is 8192 bytes even the java default buffer size is 8192. I will suggest to try
different buffer size and select the optimal one which best suites your environment.

Data Reading:

Most inefficient way of reading the text data is

while ((line = in.readLine()) != null) {
...
}

Here you are creating the String object every time you read a line. Lets say you are reading 10000 lines of file that means you are creating 10000 string objects and unnecessary time is spend in object creation, allocation and garbage collection. Instead of String you can use the character array.

For Binary Copy many write the code as below:
BufferedInputStream in = new BufferedInputStream(fis);
BufferedOutputStream out = new BufferedOutputStream(ost);
FileInputStream fis = new FileInputStream(src);
FileOutputStream ost = new FileOutputStream(dst);
byte[] buffer = new byte[8192];

while (true) {
int amountRead = in.read(buffer);
if (amountRead == -1) {
break;
}
out.write(buffer, 0, amountRead);
}

If you observer the out.write method the buffer and amount read are same so every time it will be flushed. So if file is huge it will have significant impact. So here while creating the new BufferedOutputStream(ost, size) use the size option and also use the write method instead of the previous one.

After the nio package is releases there are various option to read out of which one of very interesting is the ByteBuffer class.

ByteBuffer read the data repeatedly it keeps the track of the last byte written so that you can be assured of keep writing and rest it will take care. It doesn't mean that you can read endless data ByteBuffer has the limit. Once the limit is reached you need to flip.

ByteBuffer had following concept:

* Capacity - Size of the internal byte[].
* Position - Last byte index filled.
* Limit - Limit = capacity while reading and one past last filled byte while emptying.
* Mark - Bookmark ( optional )

ByteBuffer data is read from buffer starting position to read and while writing data is written from starting at ByteBuffer position upto limit. If you observer the position will advance till the limit and no further reading will be possible as position == limit. So you needs to do flip in ByteBuffer which will basically sets the position to 0 (start), and limit to the position
(previous position to be exact, or rather the end of useful input).


Different ways of Copy:

1) Conventional Way Of File Copy:


public void copyFile(File src, File dst, int buffLen) throws IOException {

BufferedInputStream in = null;
BufferedOutputStream out = null;
FileInputStream fis = null;
FileOutputStream ost = null;
byte[] buffer = new byte[buffLen];
try {
fis =
ost = new FileOutputStream(dst);
in = new BufferedInputStream(fis);
out = new BufferedOutputStream(ost);
while (true) {
int amountRead = in.read(buffer);
if (amountRead == -1) {
break;
}
out.write(buffer, 0, amountRead);
}
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
if (fis != null) {
fis.close();
}
if (ost != null) {
ost.close();
}

}
}

Here we are using the Buffered Stream to read and write.

2) Using the nio package and lets JVM decide the best way to copy:

public void copyUsingFileChannelIntenalTransfer(File source, File destination) throws IOException {
FileChannel in = null;
FileChannel out = null;
try {
in = new FileInputStream(source).getChannel();
out = new FileOutputStream(destination).getChannel();
// JavaVM does its best to do this as native I/O operations.
in.transferTo(0, in.size(), out);
// Closing file channels will close corresponding stream objects as well.
} finally {
out.close();
in.close();
}
}
Here we are depending on the JVM to decide the best buffer to make it as native I/O operation.

3) Copy using ByteChannel and Bytebuffer :
public void copyUsingByteChannel(File source, File destination, int bufferSize) throws IOException {
final InputStream input = new FileInputStream(source);
final OutputStream output = new FileOutputStream(destination);
final ReadableByteChannel inputChannel = Channels.newChannel(input);
final WritableByteChannel outputChannel = Channels.newChannel(output);
try {
final ByteBuffer byteBuffer = ByteBuffer.allocateDirect(bufferSize);
while (inputChannel.read(byteBuffer) != -1) {
// preparing for write by moving the limit to position
// and making position to zero
byteBuffer.flip();
// Writing to channel output stream.
outputChannel.write(byteBuffer);
// If there is any bytes left between postion and limit transfer
// it to front else same result as clear.
byteBuffer.compact();
}
//There are chances that after compact some bytes might left between
// position and limit so that also needs to be written.
byteBuffer.flip();
// Writing the remaining bytes if there is any
while (byteBuffer.hasRemaining()) {
outputChannel.write(byteBuffer);
}
} finally {
inputChannel.close();
outputChannel.close();
}
}
Here we are using the ByteChannel and ByteBuffer to copy please take note of comments for understanding.

4) Copy using MappedByteBuffer :

public void copyUsingMappedByteBuffer(File source, File destination) throws IOException {
FileInputStream fi = new FileInputStream(source);
FileChannel fic = fi.getChannel();
// Here also we are relying on the jvm and os to determine the
// buffer size
MappedByteBuffer mbuf = fic.map(
FileChannel.MapMode.READ_ONLY, 0, source.length());
fic.close();
fi.close();
FileOutputStream fo = new FileOutputStream(destination);
FileChannel foc = fo.getChannel();
foc.write(mbuf);
foc.close();
fo.close();
}

Here we are using the Mapped Byte Buffer and completely relying on jvm to determine the optimal buffer size.

Result:
After rigorous testing with different file size and different buffer size I came to
conclusion that the option no 3 is the fastest and consistent.
We were able to achieve more than 65% of performance improvement by opting to option no 3.
I will update this blog with the throughput data soon.

Friday, February 11, 2011

Class Loader

Class Loader

Class loader is responsible for loading the class. ClassLoader finds and loads the byte codes for the class definitions. Once loaded, they are verified before the ClassLoader can create actual classes. Now one question may arise who loads this classloader class, it is bootstrap also know as Primordial Class Loader.

Primordial Class Loader uses the native library to open and read Java class files from the disk into byte arrays and are platform depended. This class loader will load the core java class whose package starts with java.*. Once the core java classes are loaded it will try to load the extension classes which starts with javax.* and then finally application classes. All these loading works under delegate method one delegating to others.

Lets start writing our own class loader which will load the class from particular directory from the disk.

In order to write our own classloader we need to extend it from ClassLoader object

public class MyClassLoader extends ClassLoader

we had one method to load the class

protected synchronized Class loadClass(String dirName, String className, boolean resolve)
throws ClassNotFoundException {

Step 1: We need to find out whether that class is already loaded or not if loaded then just return that class.

Class cls = findLoadedClass(className);
if (cls != null) {
return cls;
}
Step 2: Getting the full fledge class name
String clsFile = className.replace('.', '/') + ".class";
clsFile = dirName+clsFile;

Step 3 : Security Checks.
Now here is the important step by default java runs with security manager disabled so if you want to run by enabling the security Manger you need to pass the following commands as arguments to java -Djava.security.manager -Djava.security.policy==/home/milind/.java.policy

Classloader should call the security manager to check whether particular classes are to be loaded or defined. So we will first call checkPackageDefinition() method of the security manager so that the security manager can prevent an untrusted class from defining classes in a particular package. and then we will call checkPackageAccess() method of the security manager so that the security manager can prevent certain classes from being loaded. By this way you can ensure that untrusted classes do not directly call classes in that package by placing the appropriate logic into the checkPackageAccess() method of your SecurityManager and also prevent an untrusted class from loading a new class into the java.lang package.

Classic example are Applet browser runs with own security manger and grants the correct access.

SecurityManager securityManager = System.getSecurityManager();
if( securityManager !=null) {
securityManager.checkPackageDefinition(packageName);
securityManager.checkPackageAccess(packageName);
}

Note securtiyManager can be null if you run the code without security manage enabled.


Step4: Getting the ByteStream of the .class file.

Step5: Converting the bytestream to java class and resolving it by calling the Classloader Methods.
cls = defineClass(className, classBytes, 0, classBytes.length);
if (resolve) {
resolveClass(cls);
}


Complete Code:
public class MyClassLoader extends ClassLoader {
private static final int BUFFER_SIZE = 8192;
protected synchronized Class loadClass(String className, boolean resolve)
throws ClassNotFoundException {
return loadClass(null, className, resolve);
}
protected synchronized Class loadClass(String dirName, String className, boolean resolve)
throws ClassNotFoundException {
// 1. is this class already loaded?
Class cls = findLoadedClass(className);
if (cls != null) {
return cls;
}
// get class file name from class name
String clsFile = className.replace('.', '/') + ".class";
if(dirName !=null) {
clsFile = dirName+clsFile;
}
String packageName = className.substring(0,className.lastIndexOf("."));
// Checking for the security
SecurityManager securityManager = System.getSecurityManager();
if( securityManager !=null) {
securityManager.checkPackageDefinition(packageName);
securityManager.checkPackageAccess(packageName);
}
// get bytes for class
byte[] classBytes = null;
try {
InputStream in=null;
if(dirName == null){
in = getResourceAsStream(clsFile);
}else {
in = new BufferedInputStream(new FileInputStream(clsFile));
}
byte[] buffer = new byte[BUFFER_SIZE];
ByteArrayOutputStream out = new ByteArrayOutputStream();
int n = -1;
while ((n = in.read(buffer, 0, BUFFER_SIZE)) != -1) {
out.write(buffer, 0, n);
}
classBytes = out.toByteArray();
}
catch (IOException e) {
}
if (classBytes == null) {
throw new ClassNotFoundException("Cannot load class: " + className);
}
// turn the byte array into a Class
try {
cls = defineClass(className, classBytes, 0, classBytes.length);
if (resolve) {
resolveClass(cls);
}
}
catch (SecurityException e) {
// loading core java classes such as java.lang.String
// is prohibited, throws java.lang.SecurityException.
// delegate to parent if not allowed to load class
cls = super.loadClass(className, resolve);
}
return cls;
}
}

Calling:

public static void main(String[] args) throws Exception {
MyClassLoader my = new MyClassLoader();
Class cls = my.loadClass("/media/disk/milind/MyCode/classloadingtest/", "com.milind.ClassTest", false);
Object obj = cls.newInstance();
Method method = cls.getMethod("getDesc");
Object returnObj = method.invoke(obj,null);
System.out.println(returnObj);
}









Thursday, February 10, 2011

String Vs StringBuilder

String Vs StringBuilder

Many time question comes into mind when to use String and when to use StringBuilder. Rule of thumb is that when you want to append the string it is best practice to use StringBuilder rather than appending the String object which is immutable.

Lets look at some example below lets to find out the performance difference between String and StringBuilder.

Testing String:

import java.util.Calendar;

public class StringTest {
public static void main(String[] args) {
long startTime = Calendar.getInstance().getTimeInMillis();
String test = "Testing";
test += "String";
test +="For Permormance";
test +="during append";
long endTime = Calendar.getInstance().getTimeInMillis();
System.out.println("Time Taken in Millisec ="+(endTime -startTime) + " to display String :" +test);
}
}

When you run that it the output will be :
Time Taken in Millisec =0 to display String :TestingStringFor Permormanceduring append


Testing StringBuilder:
import java.util.Calendar;

public class StringBuilderTest {

public static void main(String[] args) {

long startTime = Calendar.getInstance().getTimeInMillis();
StringBuilder testBuilder = new StringBuilder("Testing");
testBuilder.append("String");
testBuilder.append("For Permormance");
testBuilder.append("during append");
long endTime = Calendar.getInstance().getTimeInMillis();
System.out.println("Time Taken in Millisec ="+(endTime -startTime) + " to display String :" +testBuilder.toString());
}
}

When you run it the output will be:
Time Taken in Millisec =0 to display String :TestingStringFor Permormanceduring append

If you see the output in terms of performance is same for String and StringBuilder so question arise why not to use the String straightly rather then using the StringBuilder ?

Here is catch even when you are appending the String straightly compiler is smart enough to use the StringBuilder internally.

There is one tool javap - The Java Class File Disassembler which comes with the JDK lets use that try to find out JVM bytecode.

javap -c StringTest and the outcome will be:

public static void main(java.lang.String[]);
Code:
0: invokestatic #2; //Method java/util/Calendar.getInstance:()Ljava/util/Calendar;
3: invokevirtual #3; //Method java/util/Calendar.getTimeInMillis:()J
6: lstore_1
7: ldc #4; //String Testing
9: astore_3
10: new #5; //class java/lang/StringBuilder
13: dup
14: invokespecial #6; //Method java/lang/StringBuilder."":()V
17: aload_3
18: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: ldc #8; //String String
23: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
26: invokevirtual #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
29: astore_3
30: new #5; //class java/lang/StringBuilder
33: dup
34: invokespecial #6; //Method java/lang/StringBuilder."":()V
37: aload_3
38: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
41: ldc #10; //String For Permormance
43: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
46: invokevirtual #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
49: astore_3
50: new #5; //class java/lang/StringBuilder
53: dup
54: invokespecial #6; //Method java/lang/StringBuilder."":()V
57: aload_3
58: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
61: ldc #11; //String during append
63: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
66: invokevirtual #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
69: astore_3
70: invokestatic #2; //Method java/util/Calendar.getInstance:()Ljava/util/Calendar;
73: invokevirtual #3; //Method java/util/Calendar.getTimeInMillis:()J
76: lstore 4
78: getstatic #12; //Field java/lang/System.out:Ljava/io/PrintStream;
81: new #5; //class java/lang/StringBuilder
84: dup
85: invokespecial #6; //Method java/lang/StringBuilder."":()V
88: ldc #13; //String Time Taken in Millisec =
90: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
93: lload 4
95: lload_1
96: lsub
97: invokevirtual #14; //Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
100: ldc #15; //String to display String :
102: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
105: aload_3
106: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
109: invokevirtual #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
112: invokevirtual #16; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
115: return

}


If you are familiar with assembly language you can dig it further, but if you are not it is simple to interpret if you see for each String operation += the JVM had created a separate StringBuilder object and append the given String and again assign back to the String Object using the toString(). Please refer line no 14, 34 and 54.


Now lets do the same for StringBuilder
javap -c StringBuilderTest and the outcome will be:

public class StringBuilderTest extends java.lang.Object{
public StringBuilderTest();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: return

public static void main(java.lang.String[]);
Code:
0: invokestatic #2; //Method java/util/Calendar.getInstance:()Ljava/util/Calendar;
3: invokevirtual #3; //Method java/util/Calendar.getTimeInMillis:()J
6: lstore_1
7: new #4; //class java/lang/StringBuilder
10: dup
11: ldc #5; //String Testing
13: invokespecial #6; //Method java/lang/StringBuilder."":(Ljava/lang/String;)V
16: astore_3
17: aload_3
18: ldc #7; //String String
20: invokevirtual #8; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
23: pop
24: aload_3
25: ldc #9; //String For Permormance
27: invokevirtual #8; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
30: pop
31: aload_3
32: ldc #10; //String during append
34: invokevirtual #8; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
37: pop
38: invokestatic #2; //Method java/util/Calendar.getInstance:()Ljava/util/Calendar;
41: invokevirtual #3; //Method java/util/Calendar.getTimeInMillis:()J
44: lstore 4
46: getstatic #11; //Field java/lang/System.out:Ljava/io/PrintStream;
49: new #4; //class java/lang/StringBuilder
52: dup
53: invokespecial #12; //Method java/lang/StringBuilder."":()V
56: ldc #13; //String Time Taken in Millisec =
58: invokevirtual #8; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
61: lload 4
63: lload_1
64: lsub
65: invokevirtual #14; //Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
68: ldc #15; //String to display String :
70: invokevirtual #8; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
73: aload_3
74: invokevirtual #16; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
77: invokevirtual #8; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
80: invokevirtual #16; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
83: invokevirtual #17; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
86: return

}

You can clearly see that StringBuilder Object was created only Once at line no 13 and rest of the time append was called to append it to StringBuilder.

This is a very simple code and you can see the difference when you use String instead of StringBuilder the compiler had created StringBuilder object implicitly for 3 times and use toString call also for 3 times. And in case of StringBuilder it was only once. Object creation is expensive and if the code is bigger than there can be huge difference in case of performance and memory utilization.


Conclusion:

Use StringBuilder whenever you want to append the String.







Friday, February 4, 2011

How to create queue and consumers dynamically using Spring AMQP

Creating Queues and Consumers Dynamically using Spring AMQP

In my career I had used the JMS part extensively and recently I was doing the feasibility study of shifting to the RabbitMQ. RabbitMQ is really very robust and highly scalable but only stuff is that it is written in Erlang programming language as against the common practice of writing in Java. So how one will connect to RabbitMQ through Java ? RabbitMQ had provided the client library for connecting from Java but they are just basic one and as developer we need to write lots of code for better management.

RabbitMQ is product from the Spring Community so I decided to use the Spring-AMQP library to connect and use the normal producer and consumer pattern. Now Spring AMQP use the standard Spring 3.0 @Configuration to create the producer and consumers. So here we need to tell the queue name , routing key and all configuration during the context starts. Also you cannot reuse the @Configuration Class to create several Bean Object out of the same.

But my requirement was altogether very absurd to create the Queue and Consumers Dynamically which is not so easily possible and no help is available on the net for the same. After digging in depth of how Spring AMQP works I was able to do so.

I am assuming that people are already aware of the library required for the Spring AMQP if not download the sample code of Spring AMQP HellowWorld example open its maven project in your choice of your IDE and create the package as described below.


First Lets Create the producer:

package com.milind.spring.amqp.direct;

import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.SingleConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.JsonMessageConverter;

/**
*
* @author milind
*/
public class ProducerConfiguration {

private String queueName;
private String routingKey;
private RabbitTemplate rabbitTemplate;

public ProducerConfiguration() {

}

public ProducerConfiguration(String queueName, String routingKey) {
this.queueName = queueName;
this.routingKey = routingKey;
this.rabbitTemplate = rabbitTemplate();
RabbitAdmin admin = new RabbitAdmin(this.rabbitTemplate.getConnectionFactory());
admin.declareQueue(new Queue(this.queueName));
}

public void setQueueName(String queueName) {
this.queueName = queueName;
}

public void setRoutingKey(String routingKey) {
this.routingKey = routingKey;
}
public String getQueueName() {
return queueName;
}

public String getRoutingKey() {
return routingKey;
}
public RabbitTemplate rabbitTemplate() {
RabbitTemplate template = new RabbitTemplate(connectionFactory());
//The routing key is set to the name of the queue by the broker for the default exchange.
template.setRoutingKey(this.routingKey);
//Where we will synchronously receive messages from
template.setQueue(this.queueName);
template.setMessageConverter(new JsonMessageConverter());
return template;
}

public ConnectionFactory connectionFactory() {
SingleConnectionFactory connectionFactory = new SingleConnectionFactory("localhost");
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
return connectionFactory;
}

public void send(String s) {

this.rabbitTemplate.convertAndSend(s);
}
}


Now in order to Create the Consumer Config we had to do one trick, we need to create our Own MessageListner by extending SimpleMessageListenerContainer this is needed as the doStart() method is protected in SimpleMessageListenerContainer.

package com.milind.spring.amqp.direct;

import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;

/**
*
* @author milind
*/
public class ConsumerSimpleMessageListenerContainer extends SimpleMessageListenerContainer{

public void startConsumers() throws Exception {
super.doStart();
}

}

Now we can create first the Consumer Handler which will handle the incoming message.

package com.milind.spring.amqp.direct;

public class ConsumerHandler {

public void handleMessage(String text) {
System.out.println("Received--------------------------: " + text);
}
}

Finally creating the consumer configuration

package com.milind.spring.amqp.direct;

import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.SingleConnectionFactory;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.amqp.support.converter.JsonMessageConverter;

/**
*
* @author milind
*/
public class ConsumerConfig {

private String queueName;
private String routingKey;
private int onOfConsumer;

public int getOnOfConsumer() {
return onOfConsumer;
}

public void setOnOfConsumer(int onOfConsumer) {
this.onOfConsumer = onOfConsumer;
}

public String getQueueName() {
return queueName;
}

public void setQueueName(String queueName) {
this.queueName = queueName;
}

public String getRoutingKey() {
return routingKey;
}

public void setRoutingKey(String routingKey) {
this.routingKey = routingKey;
}

public ConsumerConfig(String queueName, String routingKey, int onOfConsumer) throws Exception {
this.queueName = queueName;
this.routingKey = routingKey;
this.onOfConsumer = onOfConsumer;
ConsumerSimpleMessageListenerContainer container = new ConsumerSimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory());
container.setQueueName(this.queueName);
container.setConcurrentConsumers(this.onOfConsumer);
container.setMessageListener(new MessageListenerAdapter(new ConsumerHandler(), new JsonMessageConverter()));
container.startConsumers();
}

public ConnectionFactory connectionFactory() {
SingleConnectionFactory connectionFactory = new SingleConnectionFactory("localhost");
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
return connectionFactory;
}
}

Client/Testing:

package com.milind.spring.amqp.direct;

import java.util.concurrent.TimeUnit;

/**
*
* @author milind
*/
public class Test {
public static void main(String[] args) throws InterruptedException, Exception {
ProducerConfiguration producer = new ProducerConfiguration("q1", "q1");
ConsumerConfig consumer = new ConsumerConfig("q1", "q1", 5);
int cout = 0;
while (true) {

producer.send("Str: " + cout);
TimeUnit.SECONDS.sleep(2);
cout++;

}
}
}



Now start the rabbitmq server.

You can see the queues are created in rabbitMq : sudo rabbitmqctl list_queues
Listing queues ...
q1 0
...done.

Also checking how many consumers are created:
sudo rabbitmqctl list_consumers
Listing consumers ...
q1 <'rabbit@milind-laptop'.1065.0> amq.ctag-bJlPSH2rVzOV+BDUSWjonw== false
q1 <'rabbit@milind-laptop'.1060.0> amq.ctag-Z2Gq2S0a8i1m0RlvftUr5Q== false
q1 <'rabbit@milind-laptop'.1080.0> amq.ctag-0cZkWybV6LFDgWoBslI3qQ== false
q1 <'rabbit@milind-laptop'.1075.0> amq.ctag-riIoQhH7QcnGpZOeqY4hqA== false
q1 <'rabbit@milind-laptop'.1070.0> amq.ctag-zpOjTp7URsmwRDY7NeDB4w== false
...done.

Five are created as desired

and Finally consumers are getting the Message as below:
Received--------------------------: Str: 0
Received--------------------------: Str: 1
Received--------------------------: Str: 2
Received--------------------------: Str: 3







Structural Design Pattern : Composite

Composite Design Pattern:
Word composite mean object contain another object.

Composite Pattern is Tree Structure of simple and composite objects to represent part-whole hierarchy.


Classic real time Example is the Family hierarchy. Lets try to put it into some design


( Click to enlarge)


Code:

Component:

package com.milind.gof.structural.composite;

/**
*
* @author milind
*/
public interface Family {

public void print();

}

Composite:

package com.milind.gof.structural.composite;

import java.util.ArrayList;

/**
*
* @author milind
*/
public class Parnet implements Family{


private String name;
private ArrayList arr;

public Parnet(String name) {
this.name = name;
this.arr = new ArrayList() ;
}

public void addChild(Family ch) {
this.arr.add(ch);
}

public void print() {
for(Family c : arr) {
System.out.println(c);
if(c instanceof Parnet) {
c.print();
}
}
}

@Override
public String toString() {
return "Parent: "+this.name;
}
}

Leaf:

package com.milind.gof.structural.composite;

/**
*
* @author milind
*/
public class Child implements Family{

private String name;

public Child(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {

return "Child: "+ this.name;
}

public void print() {
}
}

Client:

package com.milind.gof.structural.composite;

/**
*
* @author milind
*/
public class Main {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {

Parnet dhirubhai = new Parnet("Dhirubhai");
Parnet anil = new Parnet("Anil");
Parnet mukesh = new Parnet("Mukesh");

Child anil_1 = new Child("Anil_1");
Child anil_2 = new Child("Anil_2");

Child M1 = new Child("M1");
Child M2 = new Child("M2");

//Adding Anil children
anil.addChild(anil_1);
anil.addChild(anil_2);
//Adding Mukesh Children
mukesh.addChild(M1);
mukesh.addChild(M2);
//Adding anil and Mukesj to dhirubhai.
dhirubhai.addChild(anil);
dhirubhai.addChild(mukesh);
//printing dhirubhia's family.
dhirubhai.print();
}
}