Example usage for io.netty.util.concurrent Future addListener

List of usage examples for io.netty.util.concurrent Future addListener

Introduction

In this page you can find the example usage for io.netty.util.concurrent Future addListener.

Prototype

Future<V> addListener(GenericFutureListener<? extends Future<? super V>> listener);

Source Link

Document

Adds the specified listener to this future.

Usage

From source file:com.linecorp.armeria.server.Server.java

License:Apache License

private void stop1(CompletableFuture<Void> future, EventLoopGroup bossGroup) {
    // FIXME(trustin): Shutdown and terminate the blockingTaskExecutor.
    //                 Could be fixed while fixing https://github.com/line/armeria/issues/46

    final Future<?> bossShutdownFuture;
    if (bossGroup != null) {
        bossShutdownFuture = bossGroup.shutdownGracefully();
        this.bossGroup = null;
    } else {/*from w  w w  .j a  va2 s  .c  o m*/
        bossShutdownFuture = ImmediateEventExecutor.INSTANCE.newSucceededFuture(null);
    }

    bossShutdownFuture.addListener(f1 -> {
        // All server ports have been unbound.
        primaryActivePort = null;
        activePorts.clear();

        // Shut down the workers.
        final EventLoopGroup workerGroup = this.workerGroup;
        final Future<?> workerShutdownFuture;
        if (workerGroup != null) {
            workerShutdownFuture = workerGroup.shutdownGracefully();
            this.workerGroup = null;
        } else {
            workerShutdownFuture = ImmediateEventExecutor.INSTANCE.newSucceededFuture(null);
        }

        workerShutdownFuture.addListener(f2 -> {
            stateManager.enter(State.STOPPED);
            completeFuture(future);
        });
    });
}

From source file:com.mobicage.rogerthat.plugins.news.NewsChannel.java

License:Apache License

public void connect() {
    if (TestUtils.isRunningTest()) {
        return;//w w w  .  j av a2  s  .  com
    }
    T.NEWS();
    if (mIsConnected) {
        L.d("Already connected to news channel");
        return;
    } else if (!mService.getNetworkConnectivityManager().isConnected()) {
        L.d("Cannot connect to news channel: no internet connection.");
        return;
    } else if (mHost == null) {
        L.d("Not connecting to news channel because no host was found");
        return;
    } else if (mPort == -1) {
        L.d("Not connecting to news channel because no port was found");
        return;
    }
    mIsRetryingToConnect = true;
    L.d("Attemping to connect to news channel...");
    final SslContext sslCtx;
    if (CloudConstants.NEWS_CHANNEL_SSL) {
        try {
            if (CloudConstants.NEWS_CHANNEL_MUST_VALIDATE_SSL_CERTIFICATE) {
                TrustManagerFactory factory = TrustManagerFactory
                        .getInstance(TrustManagerFactory.getDefaultAlgorithm());
                KeyStore keyStore = KeyStore.getInstance("AndroidCAStore"); // Gets the default system keystore
                keyStore.load(null, null);
                factory.init(keyStore);
                sslCtx = SslContextBuilder.forClient().trustManager(factory).build();
            } else {
                sslCtx = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE)
                        .build();
            }
        } catch (NoSuchAlgorithmException | KeyStoreException | CertificateException | IOException e) {
            L.bug(e);
            return;
        }
    } else {
        sslCtx = null;
    }
    if (mEventLoopGroup == null) {
        mEventLoopGroup = new NioEventLoopGroup();
    }
    Bootstrap b = new Bootstrap();
    b.group(mEventLoopGroup).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true)
            .handler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    ChannelPipeline p = ch.pipeline();
                    if (sslCtx != null) {
                        SslHandler sslHandler = sslCtx.newHandler(ch.alloc(), mHost, mPort);
                        Future<Channel> handshakeDone = sslHandler.handshakeFuture();
                        handshakeDone.addListener(new GenericFutureListener<Future<? super Channel>>() {
                            @Override
                            public void operationComplete(Future<? super Channel> future) throws Exception {
                                authenticate();
                            }
                        });
                        p.addLast(sslHandler);
                    }
                    // decoder
                    p.addLast(new DelimiterBasedFrameDecoder(102400, Delimiters.lineDelimiter()));
                    p.addLast(new StringDecoder(Charset.forName("UTF-8")));

                    //encoder
                    p.addLast(new StringEncoder(Charset.forName("UTF-8")));
                    p.addLast(NewsChannel.this);
                }
            });
    // Bind and start to accept incoming connections.
    mChannel = b.connect(mHost, mPort).channel();
}

From source file:com.relayrides.pushy.apns.ApnsClient.java

License:Open Source License

/**
 * <p>Sends a push notification to the APNs gateway.</p>
 *
 * <p>This method returns a {@code Future} that indicates whether the notification was accepted or rejected by the
 * gateway. If the notification was accepted, it may be delivered to its destination device at some time in the
 * future, but final delivery is not guaranteed. Rejections should be considered permanent failures, and callers
 * should <em>not</em> attempt to re-send the notification.</p>
 *
 * <p>The returned {@code Future} may fail with an exception if the notification could not be sent. Failures to
 * <em>send</em> a notification to the gatewayi.e. those that fail with exceptionsshould generally be considered
 * non-permanent, and callers should attempt to re-send the notification when the underlying problem has been
 * resolved.</p>/*from w  w w  .j a  v  a2 s.c  o  m*/
 *
 * <p>In particular, attempts to send a notification when the client is not connected will fail with a
 * {@link ClientNotConnectedException}. If the client was previously connected and has not been explicitly
 * disconnected (via the {@link ApnsClient#disconnect()} method), the client will attempt to reconnect
 * automatically. Callers may wait for a reconnection attempt to complete by waiting for the {@code Future} returned
 * by the {@link ApnsClient#getReconnectionFuture()} method.</p>
 *
 * @param notification the notification to send to the APNs gateway
 *
 * @param <T> the type of notification to be sent
 *
 * @return a {@code Future} that will complete when the notification has been either accepted or rejected by the
 * APNs gateway
 *
 * @since 0.8
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public <T extends ApnsPushNotification> Future<PushNotificationResponse<T>> sendNotification(
        final T notification) {
    final Future<PushNotificationResponse<T>> responseFuture;
    final long notificationId = this.nextNotificationId.getAndIncrement();

    // Instead of synchronizing here, we keep a final reference to the connection ready promise. We can get away
    // with this because we're not changing the state of the connection or its promises. Keeping a reference ensures
    // we won't suddenly "lose" the channel and get a NullPointerException, but risks sending a notification after
    // things have shut down. In that case, though, the returned futures should fail quickly, and the benefit of
    // not synchronizing for every write seems worth it.
    final ChannelPromise connectionReadyPromise = this.connectionReadyPromise;

    if (connectionReadyPromise != null && connectionReadyPromise.isSuccess()
            && connectionReadyPromise.channel().isActive()) {
        final Channel channel = connectionReadyPromise.channel();
        final Promise<PushNotificationResponse<ApnsPushNotification>> responsePromise = new DefaultPromise(
                channel.eventLoop());

        channel.writeAndFlush(new PushNotificationAndResponsePromise(notification, responsePromise))
                .addListener(new GenericFutureListener<ChannelFuture>() {

                    @Override
                    public void operationComplete(final ChannelFuture future) throws Exception {
                        if (future.isSuccess()) {
                            ApnsClient.this.metricsListener.handleNotificationSent(ApnsClient.this,
                                    notificationId);
                        } else {
                            responsePromise.tryFailure(future.cause());
                        }
                    }
                });

        responseFuture = (Future) responsePromise;
    } else {
        log.debug("Failed to send push notification because client is not connected: {}", notification);
        responseFuture = new FailedFuture<>(GlobalEventExecutor.INSTANCE, NOT_CONNECTED_EXCEPTION);
    }

    responseFuture.addListener(new GenericFutureListener<Future<PushNotificationResponse<T>>>() {

        @Override
        public void operationComplete(final Future<PushNotificationResponse<T>> future) throws Exception {
            if (future.isSuccess()) {
                final PushNotificationResponse<T> response = future.getNow();

                if (response.isAccepted()) {
                    ApnsClient.this.metricsListener.handleNotificationAccepted(ApnsClient.this, notificationId);
                } else {
                    ApnsClient.this.metricsListener.handleNotificationRejected(ApnsClient.this, notificationId);
                }
            } else {
                ApnsClient.this.metricsListener.handleWriteFailure(ApnsClient.this, notificationId);
            }
        }
    });

    return responseFuture;
}

From source file:com.relayrides.pushy.apns.ApnsClient.java

License:Open Source License

/**
 * <p>Gracefully disconnects from the APNs gateway. The disconnection process will wait until notifications that
 * have been sent to the APNs server have been either accepted or rejected. Note that some notifications passed to
 * {@link com.relayrides.pushy.apns.ApnsClient#sendNotification(ApnsPushNotification)} may still be enqueued and
 * not yet sent by the time the shutdown process begins; the {@code Futures} associated with those notifications
 * will fail.</p>/*from   w  w w  .ja  v  a  2 s  . c o  m*/
 *
 * <p>The returned {@code Future} will be marked as complete when the connection has closed completely. If the
 * connection is already closed when this method is called, the returned {@code Future} will be marked as complete
 * immediately.</p>
 *
 * <p>If a non-null {@code EventLoopGroup} was provided at construction time, clients may be reconnected and reused
 * after they have been disconnected. If no event loop group was provided at construction time, clients may not be
 * restarted after they have been disconnected via this method.</p>
 *
 * @return a {@code Future} that will be marked as complete when the connection has been closed
 *
 * @since 0.5
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public Future<Void> disconnect() {
    log.info("Disconnecting.");
    final Future<Void> disconnectFuture;

    synchronized (this.bootstrap) {
        this.reconnectionPromise = null;
        if (this.scheduledReconnectFuture != null) {
            this.scheduledReconnectFuture.cancel(true);
        }

        final Future<Void> channelCloseFuture;

        if (this.connectionReadyPromise != null) {
            channelCloseFuture = this.connectionReadyPromise.channel().close();
        } else {
            channelCloseFuture = new SucceededFuture<>(GlobalEventExecutor.INSTANCE, null);
        }

        if (this.shouldShutDownEventLoopGroup) {
            // Wait for the channel to close before we try to shut down the event loop group
            channelCloseFuture.addListener(new GenericFutureListener<Future<Void>>() {

                @Override
                public void operationComplete(final Future<Void> future) throws Exception {
                    ApnsClient.this.bootstrap.config().group().shutdownGracefully();
                }
            });

            // Since the termination future for the event loop group is a Future<?> instead of a Future<Void>,
            // we'll need to create our own promise and then notify it when the termination future completes.
            disconnectFuture = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);

            this.bootstrap.config().group().terminationFuture().addListener(new GenericFutureListener() {

                @Override
                public void operationComplete(final Future future) throws Exception {
                    assert disconnectFuture instanceof DefaultPromise;
                    ((DefaultPromise<Void>) disconnectFuture).trySuccess(null);
                }
            });
        } else {
            // We're done once we've closed the channel, so we can return the closure future directly.
            disconnectFuture = channelCloseFuture;
        }
    }

    return disconnectFuture;
}

From source file:com.spotify.netty4.handler.codec.zmtp.ListenableFutureAdapter.java

License:Apache License

static <T> ListenableFuture<T> listenable(final Future<T> future) {
    final ListenableFutureAdapter<T> adapter = new ListenableFutureAdapter<T>();
    future.addListener(adapter);
    return adapter;
}

From source file:com.turo.pushy.apns.ApnsChannelPool.java

License:Open Source License

private void acquireWithinEventExecutor(final Promise<Channel> acquirePromise) {
    assert this.executor.inEventLoop();

    if (!this.isClosed) {
        // We always want to open new channels if we have spare capacity. Once the pool is full, we'll start looking
        // for idle, pre-existing channels.
        if (this.allChannels.size() + this.pendingCreateChannelFutures.size() < this.capacity) {
            final Future<Channel> createChannelFuture = this.channelFactory
                    .create(executor.<Channel>newPromise());
            this.pendingCreateChannelFutures.add(createChannelFuture);

            createChannelFuture.addListener(new GenericFutureListener<Future<Channel>>() {

                @Override//from   ww w.  j  a  v  a  2s.c o m
                public void operationComplete(final Future<Channel> future) {
                    ApnsChannelPool.this.pendingCreateChannelFutures.remove(createChannelFuture);

                    if (future.isSuccess()) {
                        final Channel channel = future.getNow();

                        ApnsChannelPool.this.allChannels.add(channel);
                        ApnsChannelPool.this.metricsListener.handleConnectionAdded();

                        acquirePromise.trySuccess(channel);
                    } else {
                        ApnsChannelPool.this.metricsListener.handleConnectionCreationFailed();

                        acquirePromise.tryFailure(future.cause());

                        // If we failed to open a connection, this is the end of the line for this acquisition
                        // attempt, and callers won't be able to release the channel (since they didn't get one
                        // in the first place). Move on to the next acquisition attempt if one is present.
                        ApnsChannelPool.this.handleNextAcquisition();
                    }
                }
            });
        } else {
            final Channel channelFromIdlePool = ApnsChannelPool.this.idleChannels.poll();

            if (channelFromIdlePool != null) {
                if (channelFromIdlePool.isActive()) {
                    acquirePromise.trySuccess(channelFromIdlePool);
                } else {
                    // The channel from the idle pool isn't usable; discard it and create a new one instead
                    this.discardChannel(channelFromIdlePool);
                    this.acquireWithinEventExecutor(acquirePromise);
                }
            } else {
                // We don't have any connections ready to go, and don't have any more capacity to create new
                // channels. Add this acquisition to the queue waiting for channels to become available.
                pendingAcquisitionPromises.add(acquirePromise);
            }
        }
    } else {
        acquirePromise.tryFailure(POOL_CLOSED_EXCEPTION);
    }
}

From source file:com.turo.pushy.apns.ApnsClientTest.java

License:Open Source License

@Test
@Parameters({ "true", "false" })
public void testSendManyNotificationsWithListeners(final boolean useTokenAuthentication) throws Exception {
    final int notificationCount = 1000;

    final List<SimpleApnsPushNotification> pushNotifications = new ArrayList<>();

    for (int i = 0; i < notificationCount; i++) {
        final String token = ApnsClientTest.generateRandomDeviceToken();
        final String payload = ApnsClientTest.generateRandomPayload();

        pushNotifications.add(new SimpleApnsPushNotification(token, TOPIC, payload));
    }/*from   ww  w  .ja v a  2s .c  o m*/

    final MockApnsServer server = this.buildServer(new AcceptAllPushNotificationHandlerFactory());
    final ApnsClient client = useTokenAuthentication ? this.buildTokenAuthenticationClient()
            : this.buildTlsAuthenticationClient();

    final CountDownLatch countDownLatch = new CountDownLatch(notificationCount);

    try {
        server.start(PORT).await();

        for (final SimpleApnsPushNotification pushNotification : pushNotifications) {
            final Future<PushNotificationResponse<SimpleApnsPushNotification>> future = client
                    .sendNotification(pushNotification);

            future.addListener(
                    new GenericFutureListener<Future<PushNotificationResponse<SimpleApnsPushNotification>>>() {

                        @Override
                        public void operationComplete(
                                final Future<PushNotificationResponse<SimpleApnsPushNotification>> future) {
                            if (future.isSuccess()) {
                                countDownLatch.countDown();
                            }
                        }
                    });
        }

        countDownLatch.await();
    } finally {
        client.close().await();
        server.shutdown().await();
    }
}

From source file:com.turo.pushy.apns.ApnsClientTest.java

License:Open Source License

@Test
@Parameters({ "true", "false" })
public void testRepeatedlySendSameNotification(final boolean useTokenAuthentication) throws Exception {
    final int notificationCount = 1000;

    final SimpleApnsPushNotification pushNotification = new SimpleApnsPushNotification(DEVICE_TOKEN, TOPIC,
            PAYLOAD);/*from  w  ww. ja  v a2s. c om*/

    final CountDownLatch countDownLatch = new CountDownLatch(notificationCount);

    final MockApnsServer server = this.buildServer(new AcceptAllPushNotificationHandlerFactory());
    final ApnsClient client = useTokenAuthentication ? this.buildTokenAuthenticationClient()
            : this.buildTlsAuthenticationClient();

    try {
        server.start(PORT).await();

        for (int i = 0; i < notificationCount; i++) {
            final Future<PushNotificationResponse<SimpleApnsPushNotification>> future = client
                    .sendNotification(pushNotification);

            future.addListener(
                    new GenericFutureListener<Future<PushNotificationResponse<SimpleApnsPushNotification>>>() {

                        @Override
                        public void operationComplete(
                                final Future<PushNotificationResponse<SimpleApnsPushNotification>> future) {
                            // All we're concerned with here is that the client told us SOMETHING about what happened to the
                            // notification
                            countDownLatch.countDown();
                        }
                    });
        }

        countDownLatch.await();
    } finally {
        client.close().await();
        server.shutdown().await();
    }
}

From source file:com.turo.pushy.apns.MockApnsServer.java

License:Open Source License

/**
 * <p>Shuts down this server and releases the port to which this server was bound. If a {@code null} event loop
 * group was provided at construction time, the server will also shut down its internally-managed event loop
 * group.</p>/*from w  w  w. j av  a 2 s .  c  o  m*/
 *
 * <p>If a non-null {@code EventLoopGroup} was provided at construction time, mock servers may be reconnected and
 * reused after they have been shut down. If no event loop group was provided at construction time, mock servers may
 * not be restarted after they have been shut down via this method.</p>
 *
 * @return a {@code Future} that will succeed once the server has finished unbinding from its port and, if the
 * server was managing its own event loop group, its event loop group has shut down
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public Future<Void> shutdown() {
    final Future<Void> channelCloseFuture = (this.allChannels != null) ? this.allChannels.close()
            : new SucceededFuture<Void>(GlobalEventExecutor.INSTANCE, null);

    final Future<Void> disconnectFuture;

    if (this.shouldShutDownEventLoopGroup) {
        // Wait for the channel to close before we try to shut down the event loop group
        channelCloseFuture.addListener(new GenericFutureListener<Future<Void>>() {

            @Override
            public void operationComplete(final Future<Void> future) throws Exception {
                MockApnsServer.this.bootstrap.config().group().shutdownGracefully();
            }
        });

        // Since the termination future for the event loop group is a Future<?> instead of a Future<Void>,
        // we'll need to create our own promise and then notify it when the termination future completes.
        disconnectFuture = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);

        this.bootstrap.config().group().terminationFuture().addListener(new GenericFutureListener() {

            @Override
            public void operationComplete(final Future future) throws Exception {
                assert disconnectFuture instanceof DefaultPromise;
                ((DefaultPromise<Void>) disconnectFuture).trySuccess(null);
            }
        });
    } else {
        // We're done once we've closed all the channels, so we can return the closure future directly.
        disconnectFuture = channelCloseFuture;
    }

    return disconnectFuture;
}

From source file:com.turo.pushy.apns.server.BaseHttp2Server.java

License:Open Source License

/**
 * <p>Shuts down this server and releases the port to which this server was bound. If a {@code null} event loop
 * group was provided at construction time, the server will also shut down its internally-managed event loop
 * group.</p>//from  ww  w  . j a va  2  s .  c o m
 *
 * <p>If a non-null {@code EventLoopGroup} was provided at construction time, mock servers may be reconnected and
 * reused after they have been shut down. If no event loop group was provided at construction time, mock servers may
 * not be restarted after they have been shut down via this method.</p>
 *
 * @return a {@code Future} that will succeed once the server has finished unbinding from its port and, if the
 * server was managing its own event loop group, its event loop group has shut down
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public Future<Void> shutdown() {
    final Future<Void> channelCloseFuture = this.allChannels.close();

    final Future<Void> disconnectFuture;

    if (this.shouldShutDownEventLoopGroup) {
        // Wait for the channel to close before we try to shut down the event loop group
        channelCloseFuture.addListener(new GenericFutureListener<Future<Void>>() {

            @Override
            public void operationComplete(final Future<Void> future) throws Exception {
                BaseHttp2Server.this.bootstrap.config().group().shutdownGracefully();
            }
        });

        // Since the termination future for the event loop group is a Future<?> instead of a Future<Void>,
        // we'll need to create our own promise and then notify it when the termination future completes.
        disconnectFuture = new DefaultPromise<>(GlobalEventExecutor.INSTANCE);

        this.bootstrap.config().group().terminationFuture().addListener(new GenericFutureListener() {

            @Override
            public void operationComplete(final Future future) throws Exception {
                ((Promise<Void>) disconnectFuture).trySuccess(null);
            }
        });
    } else {
        // We're done once we've closed all the channels, so we can return the closure future directly.
        disconnectFuture = channelCloseFuture;
    }

    disconnectFuture.addListener(new GenericFutureListener<Future<Void>>() {
        @Override
        public void operationComplete(final Future<Void> future) throws Exception {
            if (BaseHttp2Server.this.sslContext instanceof ReferenceCounted) {
                if (BaseHttp2Server.this.hasReleasedSslContext.compareAndSet(false, true)) {
                    ((ReferenceCounted) BaseHttp2Server.this.sslContext).release();
                }
            }
        }
    });

    return disconnectFuture;
}