-1

I am in the process of learning Java NIO APIs and was able to understand how things work except attachment object.

As far as I understand, we can create channels like socketChannels and attach an object to them. Whenever there is an event on a given channel then we can pick it up and its attached object.

Here, I have a requirement to modify this object (add one more key and value ) and register it with another channel say upstream channel. Think in terms of load balancer - Taking the request from frontend and passing it to upstream channel

The issue is when I am modifying the object for upstream channel, it gets modified for socket channel also.

To check this - I have simplified the code. Can you please let me know how attachement works.


public class Main {
    public static void main(String[] args)  {

        try{
            Selector selector = Selector.open();
            ServerSocketChannel serverSocket = ServerSocketChannel.open();
            serverSocket.bind(new InetSocketAddress("localhost", 10000));  
            serverSocket.configureBlocking(false);

            HashMap<String, Object> attr = new HashMap<>();
            attr.put("channel_type","server");
            attr.put("back_connection", "");

            SelectionKey selectionKey = serverSocket.register(selector, SelectionKey.OP_ACCEPT);
            selectionKey.attach(attr);  ----> 1 . I attach a object


            while(true){

                selector.selectNow();
                Set<SelectionKey> selectionKeySet = selector.selectedKeys();
                Iterator<SelectionKey> iter = selectionKeySet.iterator();
                while(iter.hasNext()){

                    selectionKey = iter.next();
                    attr = (HashMap)selectionKey.attachment();  ------> 3. Get the attachment object again from selectionKey 

                    System.out.println(selectionKey.channel());
                    String channelType = (String)attr.get("channel_type");
                    System.out.println( "Key is " + attr);  -----> 4. It has random_value key is present in attr  

                    if(selectionKey.isAcceptable() && channelType.equals("server")){

                        System.out.println("Server Connection is connected");
                        UUID uuid = UUID.randomUUID();
                        attr.put("random_value", uuid.toString());  ---> 2. Here I have modified the attr object

                    }


                    iter.remove();
                }

            }
        }

        catch(Exception e){
            System.out.println("Exception has occured in socket " + e);
        }
    }

My question is how come, when I added a random_value key in the hashmap, the attachment object for serverSocket changes automatically.

As per my understanding, it should be changing only when I am attaching the modified object again with the selectionKey of the channel.

voila
  • 1,594
  • 2
  • 19
  • 38

1 Answers1

0

Java is pass-by-value but object variables are references,so

selectionKey.attach(attr);

passes a reference to attr. Only the reference gets saved in the SelectionKey; a copy of attr is NOT made. So when you add to attr, the SelectionKey object sees the change.

Jim Garrison
  • 85,615
  • 20
  • 155
  • 190
  • Got it so what is the solution to these kind of problems. Should I make deep copy kind of thing ? – voila Jan 18 '22 at 04:55