Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add callback mechanism into LwM2mClientObserver for when the unexpected error occurred #941

Closed
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.eclipse.leshan.client.engine.RegistrationEngine;
import org.eclipse.leshan.client.engine.RegistrationEngineFactory;
import org.eclipse.leshan.client.observer.LwM2mClientObserver;
import org.eclipse.leshan.client.observer.LwM2mClientObserverAdapter;
import org.eclipse.leshan.client.observer.LwM2mClientObserverDispatcher;
import org.eclipse.leshan.client.resource.LwM2mObjectEnabler;
import org.eclipse.leshan.client.resource.LwM2mObjectTree;
Expand Down Expand Up @@ -115,6 +116,9 @@ public LeshanClient(String endpoint, InetSocketAddress localAddress,
createRegistrationUpdateHandler(engine, endpointsManager, bootstrapHandler, objectTree);

coapApi = new CoapAPI();

// register the shutdown observer for when the unexpected error occurred.
addObserver(new ShutdownOnUnexpectedErrorObserver(this));
}

protected LwM2mObjectTree createObjectTree(List<? extends LwM2mObjectEnabler> objectEnablers) {
Expand Down Expand Up @@ -320,4 +324,18 @@ public Map<String, ServerIdentity> getRegisteredServers() {
public InetSocketAddress getAddress(ServerIdentity server) {
return endpointsManager.getEndpoint(server).getAddress();
}

private static class ShutdownOnUnexpectedErrorObserver extends LwM2mClientObserverAdapter {
final LeshanClient client;

public ShutdownOnUnexpectedErrorObserver(final LeshanClient client) {
this.client = client;
}

@Override
public void onUnexpectedError(Throwable unexpectedError) {
LOG.error("unexpected error occurred. destroy the leshan-client", unexpectedError);
client.destroy(true);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,7 @@ public void run() {
LOG.info("Bootstrap task interrupted. ");
} catch (RuntimeException e) {
LOG.error("Unexpected exception during bootstrap task", e);
observer.onUnexpectedError(e);
}
}
}
Expand Down Expand Up @@ -564,6 +565,7 @@ public void run() {
LOG.info("Registration task interrupted. ");
} catch (RuntimeException e) {
LOG.error("Unexpected exception during registration task", e);
observer.onUnexpectedError(e);
}
}
}
Expand Down Expand Up @@ -612,6 +614,7 @@ public void run() {
LOG.info("Registration update task interrupted.");
} catch (RuntimeException e) {
LOG.error("Unexpected exception during update registration task", e);
observer.onUnexpectedError(e);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,8 @@ void onDeregistrationFailure(ServerIdentity server, DeregisterRequest request, R
String errorMessage, Exception cause);

void onDeregistrationTimeout(ServerIdentity server, DeregisterRequest request);

// ============== Unexpected Error Handling =================

void onUnexpectedError(Throwable unexpectedError);
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,8 @@ public void onDeregistrationFailure(ServerIdentity server, DeregisterRequest req
@Override
public void onDeregistrationTimeout(ServerIdentity server, DeregisterRequest request) {
}

@Override
public void onUnexpectedError(Throwable unexpectedError) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,10 @@ public void onDeregistrationTimeout(ServerIdentity server, DeregisterRequest req
}
}

@Override
public void onUnexpectedError(Throwable unexpectedError) {
for (LwM2mClientObserver observer : observers) {
observer.onUnexpectedError(unexpectedError);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@

import org.eclipse.leshan.client.LwM2mClient;
import org.eclipse.leshan.client.servers.ServerIdentity;
import org.eclipse.leshan.core.Destroyable;
import org.eclipse.leshan.core.Startable;
import org.eclipse.leshan.core.Stoppable;
import org.eclipse.leshan.core.model.ObjectModel;
import org.eclipse.leshan.core.node.LwM2mObjectInstance;
import org.eclipse.leshan.core.node.LwM2mResource;
Expand All @@ -45,6 +48,12 @@
* <p>
* Implementations of this interface should adhere to the definition of the implemented LWM2M Object type regarding
* acceptable resource IDs for the <code>read, write</code> and <code>execute</code> methods.
* An instance that implements this interface synchronizes with the lifecycle of the LeshanClient. This means when
* <p>
* {@code LeshanClient#destroy()} is called, {@code LwM2mInstanceEnabler#destroy()} is also called if it implements the
* {@link Destroyable} interface. And {@link Startable} ({@code #start()}) and {@link Stoppable} ({@code #stop()}) are
* also same as this. If you need to restart the instance, please implement {@link Startable} with {@link Stoppable}
* together.
*/
public interface LwM2mInstanceEnabler {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@
import org.eclipse.leshan.client.LwM2mClient;
import org.eclipse.leshan.client.servers.ServerIdentity;
import org.eclipse.leshan.client.servers.ServersInfoExtractor;
import org.eclipse.leshan.core.Destroyable;
import org.eclipse.leshan.core.LwM2mId;
import org.eclipse.leshan.core.Startable;
import org.eclipse.leshan.core.Stoppable;
import org.eclipse.leshan.core.model.ObjectModel;
import org.eclipse.leshan.core.node.LwM2mObject;
import org.eclipse.leshan.core.node.LwM2mObjectInstance;
Expand Down Expand Up @@ -62,7 +65,7 @@
* Implementing a {@link LwM2mInstanceEnabler} then creating an {@link ObjectEnabler} with {@link ObjectsInitializer} is
* the easier way to implement LWM2M object in Leshan client.
*/
public class ObjectEnabler extends BaseObjectEnabler {
public class ObjectEnabler extends BaseObjectEnabler implements Destroyable, Startable, Stoppable {

protected Map<Integer, LwM2mInstanceEnabler> instances;
protected LwM2mInstanceEnablerFactory instanceFactory;
Expand Down Expand Up @@ -411,4 +414,33 @@ public void setLwM2mClient(LwM2mClient client) {
instanceEnabler.setLwM2mClient(client);
}
}

@Override
public void destroy() {
for (LwM2mInstanceEnabler instanceEnabler : instances.values()) {
if (instanceEnabler instanceof Destroyable) {
((Destroyable) instanceEnabler).destroy();
} else if (instanceEnabler instanceof Stoppable) {
((Stoppable) instanceEnabler).stop();
}
}
}

@Override
public void start() {
for (LwM2mInstanceEnabler instanceEnabler : instances.values()) {
if (instanceEnabler instanceof Startable) {
((Startable) instanceEnabler).start();
}
}
}

@Override
public void stop() {
for (LwM2mInstanceEnabler instanceEnabler : instances.values()) {
if (instanceEnabler instanceof Stoppable) {
((Stoppable) instanceEnabler).stop();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import org.eclipse.leshan.client.resource.BaseInstanceEnabler;
import org.eclipse.leshan.client.servers.ServerIdentity;
import org.eclipse.leshan.core.Destroyable;
import org.eclipse.leshan.core.model.ObjectModel;
import org.eclipse.leshan.core.model.ResourceModel.Type;
import org.eclipse.leshan.core.node.LwM2mResource;
Expand All @@ -23,17 +24,19 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyDevice extends BaseInstanceEnabler {
public class MyDevice extends BaseInstanceEnabler implements Destroyable {

private static final Logger LOG = LoggerFactory.getLogger(MyDevice.class);

private static final Random RANDOM = new Random();
private static final List<Integer> supportedResources = Arrays.asList(0, 1, 2, 3, 9, 10, 11, 13, 14, 15, 16, 17, 18,
19, 20, 21);

private final Timer timer;

public MyDevice() {
// notify new date each 5 second
Timer timer = new Timer("Device-Current Time");
this.timer = new Timer("Device-Current Time");
timer.schedule(new TimerTask() {
@Override
public void run() {
Expand Down Expand Up @@ -210,4 +213,9 @@ private long getMemoryTotal() {
public List<Integer> getAvailableResourceIds(ObjectModel model) {
return supportedResources;
}

@Override
public void destroy() {
timer.cancel();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@

import org.eclipse.leshan.client.resource.BaseInstanceEnabler;
import org.eclipse.leshan.client.servers.ServerIdentity;
import org.eclipse.leshan.core.Destroyable;
import org.eclipse.leshan.core.model.ObjectModel;
import org.eclipse.leshan.core.response.ExecuteResponse;
import org.eclipse.leshan.core.response.ReadResponse;
import org.eclipse.leshan.core.util.NamedThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RandomTemperatureSensor extends BaseInstanceEnabler {
public class RandomTemperatureSensor extends BaseInstanceEnabler implements Destroyable {

private static final Logger LOG = LoggerFactory.getLogger(RandomTemperatureSensor.class);

Expand Down Expand Up @@ -113,4 +114,9 @@ private void resetMinMaxMeasuredValues() {
public List<Integer> getAvailableResourceIds(ObjectModel model) {
return supportedResources;
}

@Override
public void destroy() {
scheduler.shutdown();
}
}