TheThingsArchive / java-app-sdk

The Things Network Application SDK for Java
MIT License
30 stars 25 forks source link

Failure to reconnect on error #62

Closed james-mcgivern closed 3 years ago

james-mcgivern commented 5 years ago

We have a simple TTN client using this library. When we detect an error, e.g. connection dropped, we try and reconnect automatically but it always fails and a manual restart of the service is required. Is there any reason for this or a better way to achieve this?

Here is our client:

@Component
public class TtnClient {

private static final Logger log = LoggerFactory.getLogger(TtnClient.class);

private EventService service;
private final Client client;

@Autowired
public TtnClient(@Value("${ttn.client.region}") String region,
                 @Value("${ttn.client.appId}") String appId,
                 @Value("${ttn.client.accessKey}") String accessKey,
                 EventService eventService) throws Exception {
    log.info("Constructing TTN Client(region={}, appId={}, accessKey=**********", region, appId);
    client = new Client(region, appId, accessKey);
    service = eventService;

    client.onMessage(this::handleMessage);
    client.onActivation(this::handleActivation);
    client.onError(this::handleError);
    client.onConnected(this::handleConnection);
    client.start();
}

private void handleMessage(String deviceId, DataMessage dataMessage) {
    TtnEvent event = new TtnEvent();
    event.setDevice(deviceId);
    event.setMessage((UplinkMessage) dataMessage);

    log.info("Received TTN Event: " + event);
    try {
        service.processEvent(event);
    } catch (EventNotProcessedException e) {
        log.error("Failed to process event ({}) due to error: {}", event, e);
    }
}

private void handleActivation(String _devId, ActivationMessage _data) {
    log.info("Activation of TTN Device: " + _devId + ", address: " + _data.getDevAddr());
}

private void handleError(Throwable throwable) {
    log.error("Error processing TTN Event: " + throwable);
    try {
        client.endNow();
    } catch (Exception e) {
        log.error("Error stopping MQTT client", e);
    }
    try {
        client.start();
    } catch (Exception e) {
        log.error("Error starting MQTT client", e);
    }

}

private void handleConnection(Connection _client) {
    log.info("TTN Client is connected!");
}
}
johanstokking commented 5 years ago

I'm not too familiar with this library, but you may not be able to reuse an existing client, i.e. by calling start() on something that has errorred.