io.crate.mqtt.netty.Client.java Source code

Java tutorial

Introduction

Here is the source code for io.crate.mqtt.netty.Client.java

Source

/*
 * Copyright (c) 2012-2017 The original author or authorsgetRockQuestions()
 * ------------------------------------------------------
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Apache License v2.0 which accompanies this distribution.
 *
 * The Eclipse Public License is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * The Apache License v2.0 is available at
 * http://www.opensource.org/licenses/apache2.0.php
 *
 * You may elect to redistribute this code under either of these licenses.
 */
package io.crate.mqtt.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.mqtt.MqttDecoder;
import io.netty.handler.codec.mqtt.MqttEncoder;
import io.netty.handler.codec.mqtt.MqttMessage;
import io.netty.handler.codec.mqtt.MqttQoS;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.util.Throwables;
import org.elasticsearch.common.logging.Loggers;

import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;

/**
 * Class used just to send and receive MQTT messages without any protocol login
 * in action, just use the encoder/decoder part.
 *
 * @author andrea
 */
public class Client implements AutoCloseable {

    private static final Logger LOGGER = Loggers.getLogger(Client.class);

    private final String host;
    private final int port;
    private EventLoopGroup workerGroup;
    private Channel channel;
    private String clientId;
    private ClientNettyMQTTHandler handler;

    public Client(String host, int port) {
        this.host = host;
        this.port = port;
        clientId(UUID.randomUUID().toString());
    }

    public void connect() {
        LOGGER.debug("[mqtt-client] connect");
        handler = new ClientNettyMQTTHandler();
        workerGroup = new NioEventLoopGroup(1);
        try {
            Bootstrap b = new Bootstrap();
            b.group(workerGroup);
            b.channel(NioSocketChannel.class);
            b.option(ChannelOption.SO_KEEPALIVE, true);
            b.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    ChannelPipeline pipeline = ch.pipeline();
                    pipeline.addLast("decoder", new MqttDecoder());
                    pipeline.addLast("encoder", MqttEncoder.INSTANCE);
                    pipeline.addLast("handler", handler);
                }
            });

            // Start the client.
            channel = b.connect(host, port).sync().channel();
        } catch (Exception ex) {
            LOGGER.error("[mqtt-client] Error in client setup: " + ex.getMessage());
            workerGroup.shutdownGracefully();
            Throwables.rethrow(ex);
        }
    }

    private void clientId(String clientId) {
        this.clientId = clientId;
    }

    public String clientId() {
        return clientId;
    }

    public void sendMessage(MqttMessage msg) {
        LOGGER.debug("[mqtt-client] ==> send message");
        handler.initCallback();
        channel.writeAndFlush(msg);
    }

    public MqttMessage lastReceivedMessage() throws Exception {
        return lastReceivedMessage(1_000L);
    }

    public MqttMessage lastReceivedMessage(long timeout) throws Exception {
        try {
            LOGGER.debug("[mqtt-client] <== receive message");
            return handler.lastMessage(timeout);
        } catch (TimeoutException e) {
            throw new NoMessageReceivedException(timeout);
        }
    }

    @Override
    public void close() throws InterruptedException {
        if (channel != null && channel.closeFuture() != null) {
            // Wait until the connection is closed.
            channel.closeFuture().sync();
        }
        if (workerGroup == null) {
            throw new IllegalStateException("Invoked close on an Acceptor that wasn't initialized");
        }
        workerGroup.shutdownGracefully();
        LOGGER.debug("[mqtt-client] closed");
    }

    public void disconnect() {
        LOGGER.debug("[mqtt-client] disconnect");
        sendMessage(MqttMessages.newDisconnectMessage(MqttQoS.AT_LEAST_ONCE));
    }

    static class NoMessageReceivedException extends ExecutionException {
        NoMessageReceivedException(long timeout) {
            super("MQTT client did not receive message in time (" + String.valueOf(timeout) + "ms).");
        }
    }
}