All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.grizzly.samples.httpserver.blockinghandler.BlockingHttpHandlerSample Maven / Gradle / Ivy

There is a newer version: 4.0.2
Show newest version
/*
 * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0, which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package org.glassfish.grizzly.samples.httpserver.blockinghandler;

import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.glassfish.grizzly.Buffer;
import org.glassfish.grizzly.Connection;
import org.glassfish.grizzly.Grizzly;
import org.glassfish.grizzly.filterchain.BaseFilter;
import org.glassfish.grizzly.filterchain.FilterChainBuilder;
import org.glassfish.grizzly.filterchain.FilterChainContext;
import org.glassfish.grizzly.filterchain.NextAction;
import org.glassfish.grizzly.filterchain.TransportFilter;
import org.glassfish.grizzly.http.HttpClientFilter;
import org.glassfish.grizzly.http.HttpContent;
import org.glassfish.grizzly.http.HttpRequestPacket;
import org.glassfish.grizzly.http.server.HttpHandler;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.http.server.Request;
import org.glassfish.grizzly.http.server.Response;
import org.glassfish.grizzly.http.server.ServerConfiguration;
import org.glassfish.grizzly.http.util.Header;
import org.glassfish.grizzly.http.util.HeaderValue;
import org.glassfish.grizzly.impl.FutureImpl;
import org.glassfish.grizzly.impl.SafeFutureImpl;
import org.glassfish.grizzly.memory.Buffers;
import org.glassfish.grizzly.memory.MemoryManager;
import org.glassfish.grizzly.nio.transport.TCPNIOTransport;
import org.glassfish.grizzly.nio.transport.TCPNIOTransportBuilder;

/**
 * 

* This example demonstrates the use of a {@link HttpHandler} to echo HTTP POST data sent by * the client, back to the client. *

* *

* The is composed of two main parts (as nested classes of BlockingHttpHandlerSample) *

    *
  • Client: This is a simple HTTP based on the Grizzly {@link HttpClientFilter}. The client uses a * custom {@link org.glassfish.grizzly.filterchain.Filter} on top of the {@link HttpClientFilter} to send the * POST and read, and ultimately display, the response from the server.
  • *
  • BlockingEchoHandler: This {@link HttpHandler} is installed to the * {@link org.glassfish.grizzly.http.server.HttpServer} instance and associated with the path /echo. This * {@link HttpHandler} is fairly simple. The handler uses the {@link java.io.Reader} returned by * {@link org.glassfish.grizzly.http.server.Request#getReader()} in blocking mode. As data is received, the same data is * then immediately written to the response.
  • *
*

* */ public class BlockingHttpHandlerSample { private static final Logger LOGGER = Grizzly.logger(BlockingHttpHandlerSample.class); public static void main(String[] args) { // create a basic server that listens on port 8080. final HttpServer server = HttpServer.createSimpleServer(); final ServerConfiguration config = server.getServerConfiguration(); // Map the path, /echo, to the BlockingEchoHandler config.addHttpHandler(new BlockingEchoHandler(), "/echo"); try { server.start(); Client client = new Client(); client.run(); } catch (IOException ioe) { LOGGER.log(Level.SEVERE, ioe.toString(), ioe); } finally { server.shutdownNow(); } } // ---------------------------------------------------------- Nested Classes private static final class Client { private static final String HOST = "localhost"; private static final int PORT = 8080; public void run() throws IOException { final FutureImpl completeFuture = SafeFutureImpl.create(); // Build HTTP client filter chain FilterChainBuilder clientFilterChainBuilder = FilterChainBuilder.stateless(); // 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(); transport.setProcessor(clientFilterChainBuilder.build()); try { // start the transport transport.start(); Connection connection = null; // Connecting to a remote Web server Future 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 { // stop the transport transport.shutdownNow(); } } // ------------------------------------------------------ Nested Classes private static final class ClientFilter extends BaseFilter { private static final HeaderValue HOST_HEADER_VALUE = HeaderValue.newHeaderValue(HOST + ':' + PORT).prepare(); private static final String[] CONTENT = { "contentA-", "contentB-", "contentC-", "contentD" }; private final FutureImpl future; private final StringBuilder sb = new StringBuilder(); // ---------------------------------------------------- Constructors private ClientFilter(FutureImpl future) { this.future = future; } // ----------------------------------------- Methods from BaseFilter @SuppressWarnings({ "unchecked" }) @Override public NextAction handleConnect(FilterChainContext ctx) throws IOException { System.out.println("\nClient connected!\n"); HttpRequestPacket.Builder builder = createRequest(); HttpRequestPacket request = builder.build(); request.addHeader(Header.Host, HOST_HEADER_VALUE); System.out.println("Writing request:\n"); System.out.println(request.toString()); ctx.write(request); // write the request // for each of the content parts in CONTENT, wrap in a Buffer, // create the HttpContent to wrap the buffer and write the // content. MemoryManager mm = ctx.getConnection().getTransport().getMemoryManager(); for (int i = 0, len = CONTENT.length; i < len; i++) { HttpContent.Builder contentBuilder = request.httpContentBuilder(); Buffer b = Buffers.wrap(mm, CONTENT[i]); contentBuilder.content(b); HttpContent content = contentBuilder.build(); System.out.println(b.toStringContent()); ctx.write(content); } // since the request created by createRequest() is chunked, // we need to write the trailer to signify the end of the // POST data ctx.write(request.httpTrailerBuilder().build()); System.out.println("\n"); return ctx.getStopAction(); // discontinue filter chain execution } @Override public NextAction handleRead(FilterChainContext ctx) throws IOException { HttpContent c = ctx.getMessage(); Buffer b = c.getContent(); if (b.hasRemaining()) { sb.append(b.toStringContent()); } // Last content from the server, set the future result so // the client can display the result and gracefully exit. if (c.isLast()) { future.result(sb.toString()); } return ctx.getStopAction(); // discontinue filter chain execution } // ------------------------------------------------- Private Methods private HttpRequestPacket.Builder createRequest() { HttpRequestPacket.Builder builder = HttpRequestPacket.builder(); builder.method("POST"); builder.protocol("HTTP/1.1"); builder.uri("/echo"); builder.chunked(true); return builder; } } } // END Client /** * This handler using blocking streams to read POST data and echo it back to the client. */ private static class BlockingEchoHandler extends HttpHandler { // -------------------------------------------- Methods from HttpHandler @Override public void service(Request request, Response response) throws Exception { final char[] buf = new char[128]; Reader in = null; Writer out = null; try { in = request.getReader(); // put the stream in blocking mode out = response.getWriter(); int read; while ((read = in.read(buf)) != -1) { out.write(buf, 0, read); // echo the contents of 'buf' to the client } out.flush(); } finally { if (in != null) { try { in.close(); } catch (IOException ignore) { } } if (out != null) { try { out.close(); } catch (IOException ignore) { } } } } } // END BlockingEchoHandler }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy