public void run() throws IOException {
      final FutureImpl<String> completeFuture = SafeFutureImpl.create();

      // Build HTTP client filter chain
      FilterChainBuilder clientFilterChainBuilder = FilterChainBuilder.newInstance();
      // Add transport filter
      clientFilterChainBuilder.add(new TransportFilter());

      // Add HttpClientFilter, which transforms Buffer <-> HttpContent
      clientFilterChainBuilder.add(new HttpClientFilter());
      // Add ClientFilter
      clientFilterChainBuilder.add(new ClientFilter(completeFuture));

      // Initialize Transport
      final TCPNIOTransport transport = TCPNIOTransportBuilder.newInstance().build();
      // Set filterchain as a Transport Processor
      transport.setFilterChain(clientFilterChainBuilder.build());

      try {
        // start the transport
        transport.start();

        Connection connection = null;

        // Connecting to a remote Web server
        Future<Connection> connectFuture = transport.connect(HOST, PORT);
        try {
          // Wait until the client connect operation will be completed
          // Once connection has been established, the POST will
          // be sent to the server.
          connection = connectFuture.get(10, TimeUnit.SECONDS);

          // Wait no longer than 30 seconds for the response from the
          // server to be complete.
          String result = completeFuture.get(30, TimeUnit.SECONDS);

          // Display the echoed content
          System.out.println("\nEchoed POST Data: " + result + '\n');
        } catch (Exception e) {
          if (connection == null) {
            LOGGER.log(Level.WARNING, "Connection failed.  Server is not listening.");
          } else {
            LOGGER.log(Level.WARNING, "Unexpected error communicating with the server.");
          }
        } finally {
          // Close the client connection
          if (connection != null) {
            connection.closeSilently();
          }
        }
      } finally {
        // shutdownNow the transport
        transport.shutdownNow();
      }
    }
  @Test
  public void testCustomThreadPoolSameThreadStrategy() throws Exception {

    final int poolSize = Math.max(Runtime.getRuntime().availableProcessors() / 2, 1);
    final ThreadPoolConfig poolCfg = ThreadPoolConfig.defaultConfig();
    poolCfg.setCorePoolSize(poolSize).setMaxPoolSize(poolSize);

    final TCPNIOTransport tcpTransport =
        TCPNIOTransportBuilder.newInstance()
            .setReuseAddress(true)
            .setIOStrategy(SameThreadIOStrategy.getInstance())
            .setSelectorThreadPoolConfig(poolCfg)
            .setWorkerThreadPoolConfig(null)
            .build();
    try {
      tcpTransport.start();
    } finally {
      tcpTransport.shutdownNow();
    }
  }
  public static void main(String[] args) throws Exception {
    Connection connection = null;

    // Construct the client filter chain
    final FilterChainBuilder puFilterChainBuilder =
        FilterChainBuilder.stateless()
            // Add TransportFilter
            .add(new TransportFilter())
            // Add ADD-service message parser/serializer
            .add(new AddClientMessageFilter())
            // Add Result reporter Filter
            .add(new ResultFilter());

    // Construct TCPNIOTransport
    final TCPNIOTransport transport = TCPNIOTransportBuilder.newInstance().build();
    transport.setProcessor(puFilterChainBuilder.build());

    try {
      // Start
      transport.start();

      // Create the client connection
      final Future<Connection> connectFuture = transport.connect("localhost", PUServer.PORT);
      connection = connectFuture.get(10, TimeUnit.SECONDS);

      LOGGER.info("Enter 2 numbers separated by space (<value1> <value2>) end press <enter>.");
      LOGGER.info("Type q and enter to exit.");

      // Read user input and communicate the ADD-service
      String line;
      BufferedReader reader =
          new BufferedReader(new InputStreamReader(System.in, Charsets.ASCII_CHARSET));
      while ((line = reader.readLine()) != null) {
        if ("q".equals(line)) {
          break;
        }

        // Parse user input
        final int value1;
        final int value2;
        try {
          final String[] values = line.split(" ");

          value1 = Integer.parseInt(values[0].trim());
          value2 = Integer.parseInt(values[1].trim());
        } catch (Exception e) {
          LOGGER.warning("Bad format, repeat pls");
          continue;
        }

        // send the request to ADD-service
        final GrizzlyFuture<WriteResult> writeFuture =
            connection.write(new AddRequestMessage(value1, value2));

        final WriteResult result = writeFuture.get(10, TimeUnit.SECONDS);
        assert result != null;
      }

    } finally {
      // Close the client connection
      if (connection != null) {
        connection.closeSilently();
      }

      // Shutdown the transport
      transport.shutdownNow();
    }
  }
  public void testStandalone() throws Exception {
    TCPNIOTransport transport = TCPNIOTransportBuilder.newInstance().build();
    transport.getAsyncQueueIO().getWriter().setMaxPendingBytesPerConnection(-1);

    int messageSize = 166434;

    Connection connection = null;
    StreamReader reader = null;
    StreamWriter writer = null;

    try {
      // Enable standalone mode
      transport.configureStandalone(true);

      // Start listen on specific port
      final TCPNIOServerConnection serverConnection = transport.bind(PORT);
      // Start transport
      transport.start();

      // Start echo server thread
      final Thread serverThread = startEchoServerThread(transport, serverConnection, messageSize);

      // Connect to the server
      Future<Connection> connectFuture = transport.connect("localhost", PORT);
      connection = connectFuture.get(10, TimeUnit.SECONDS);
      assertTrue(connectFuture.isDone());

      // fill out buffer
      byte[] buffer = new byte[messageSize];
      for (int i = 0; i < messageSize; i++) {
        buffer[i] = (byte) (i % 128);
      }
      // write buffer
      writer = StandaloneProcessor.INSTANCE.getStreamWriter(connection);
      writer.writeByteArray(buffer);
      writer.flush();

      reader = StandaloneProcessor.INSTANCE.getStreamReader(connection);

      // prepare receiving buffer
      byte[] receiveBuffer = new byte[messageSize];

      Future readFuture = reader.notifyAvailable(messageSize);
      readFuture.get(20, TimeUnit.SECONDS);

      // Read the response.
      reader.readByteArray(receiveBuffer);

      assertTrue(readFuture.isDone());

      // Check the echo result
      assertTrue(Arrays.equals(buffer, receiveBuffer));

      serverThread.join(10 * 1000);
    } finally {
      if (connection != null) {
        connection.closeSilently();
      }

      transport.shutdownNow();
    }
  }
  public void testBlockingRead() throws Exception {
    final String[] clientMsgs = {"XXXXX", "Hello", "from", "client"};

    Connection connection = null;
    int messageNum = 3;

    final BlockingQueue<String> intermResultQueue = DataStructures.getLTQInstance(String.class);

    final PUFilter puFilter = new PUFilter();
    FilterChain subProtocolChain =
        puFilter
            .getPUFilterChainBuilder()
            .add(new MergeFilter(clientMsgs.length, intermResultQueue))
            .add(new EchoFilter())
            .build();

    puFilter.register(new SimpleProtocolFinder(clientMsgs[0]), subProtocolChain);

    FilterChainBuilder filterChainBuilder = FilterChainBuilder.newInstance();
    filterChainBuilder.add(new TransportFilter());
    filterChainBuilder.add(new StringFilter());
    filterChainBuilder.add(puFilter);

    final TCPNIOTransport transport = TCPNIOTransportBuilder.newInstance().build();
    transport.setFilterChain(filterChainBuilder.build());

    try {
      transport.bind(PORT);
      transport.start();

      final BlockingQueue<String> resultQueue = DataStructures.getLTQInstance(String.class);

      Future<Connection> future = transport.connect("localhost", PORT);
      connection = future.get(10, TimeUnit.SECONDS);
      assertTrue(connection != null);

      FilterChainBuilder clientFilterChainBuilder = FilterChainBuilder.newInstance();
      clientFilterChainBuilder.add(new TransportFilter());
      clientFilterChainBuilder.add(new StringFilter());
      clientFilterChainBuilder.add(
          new BaseFilter() {

            @Override
            public NextAction handleRead(FilterChainContext ctx) throws IOException {
              resultQueue.add((String) ctx.getMessage());
              return ctx.getStopAction();
            }
          });
      final FilterChain clientFilterChain = clientFilterChainBuilder.build();

      connection.setFilterChain(clientFilterChain);

      for (int i = 0; i < messageNum; i++) {
        String clientMessage = "";

        for (int j = 0; j < clientMsgs.length; j++) {
          String msg = clientMsgs[j] + "-" + i;
          Future<WriteResult> writeFuture = connection.write(msg);

          assertTrue("Write timeout loop: " + i, writeFuture.get(10, TimeUnit.SECONDS) != null);

          final String srvInterm = intermResultQueue.poll(10, TimeUnit.SECONDS);

          assertEquals("Unexpected interm. response (" + i + ", " + j + ")", msg, srvInterm);

          clientMessage += msg;
        }

        final String message = resultQueue.poll(10, TimeUnit.SECONDS);

        assertEquals("Unexpected response (" + i + ")", clientMessage, message);
      }
    } finally {
      if (connection != null) {
        connection.closeSilently();
      }

      transport.shutdownNow();
    }
  }
  public void testBlockingReadError() throws Exception {
    final String[] clientMsgs = {"ZZZZZ", "Hello", "from", "client"};

    Connection connection = null;

    final BlockingQueue intermResultQueue = DataStructures.getLTQInstance();

    final PUFilter puFilter = new PUFilter();
    FilterChain subProtocolChain =
        puFilter
            .getPUFilterChainBuilder()
            .add(new MergeFilter(clientMsgs.length, intermResultQueue))
            .add(new EchoFilter())
            .build();

    puFilter.register(new SimpleProtocolFinder(clientMsgs[0]), subProtocolChain);

    FilterChainBuilder filterChainBuilder = FilterChainBuilder.newInstance();
    filterChainBuilder.add(new TransportFilter());
    filterChainBuilder.add(new StringFilter());
    filterChainBuilder.add(puFilter);

    TCPNIOTransport transport = TCPNIOTransportBuilder.newInstance().build();
    transport.setFilterChain(filterChainBuilder.build());

    try {
      transport.bind(PORT);
      transport.start();

      Future<Connection> future = transport.connect("localhost", PORT);
      connection = future.get(10, TimeUnit.SECONDS);
      assertTrue(connection != null);

      FilterChainBuilder clientFilterChainBuilder = FilterChainBuilder.newInstance();
      clientFilterChainBuilder.add(new TransportFilter());
      clientFilterChainBuilder.add(new StringFilter());
      final FilterChain clientFilterChain = clientFilterChainBuilder.build();

      connection.setFilterChain(clientFilterChain);

      String msg = clientMsgs[0];
      Future<WriteResult> writeFuture = connection.write(msg);

      assertTrue("Write timeout", writeFuture.get(10, TimeUnit.SECONDS) != null);

      final String srvInterm = (String) intermResultQueue.poll(10, TimeUnit.SECONDS);

      assertEquals("Unexpected interm. response", msg, srvInterm);

      connection.closeSilently();
      connection = null;

      final Exception e = (Exception) intermResultQueue.poll(10, TimeUnit.SECONDS);

      assertTrue(
          "Unexpected response. Exception: " + e.getClass() + ": " + e.getMessage(),
          e instanceof IOException);
    } finally {
      if (connection != null) {
        connection.closeSilently();
      }

      transport.shutdownNow();
    }
  }