sane-city / wot-servient

W3C Web of Things implementation for Java
MIT License
30 stars 5 forks source link

MqttProtocolServer::stop won't destroy exposed Things #6

Closed Dnnd closed 4 years ago

Dnnd commented 4 years ago

Expected behavior

Wot::destroy (which eventually invokes ProtocolServer::stop) will clean all of exposed Thing Descriptions, so it's unnecessary to explicitly call ExposedThing::destroy method before Wot::destroy.

Observed behavior

MqttProtocolServer::stop will neither unexpose thing descriptions nor dispose thing's internal subscriptions.

Consider the following code:

public class Test {
    public static final String PROPERTY_NAME = "property";

    public static void main(String[] args) throws WotException, ExecutionException, InterruptedException {
        Config config = ConfigFactory
                .parseString("wot.servient.servers = [\"city.sane.wot.binding.mqtt.MqttProtocolServer\"]");

        config = config.withFallback(ConfigFactory.load());
        Wot wot = DefaultWot.serverOnly(config);
        Thing thing = new Thing.Builder()
                .addProperty(PROPERTY_NAME, new ThingProperty.Builder().setType("string").build())
                .build();
        ExposedThing exposedThing = wot.produce(thing).expose().get();
        wot.destroy();
        exposedThing.getProperty(PROPERTY_NAME).write("example").get();
    }
}

Output:


20:50:13.040 | main | DEBUG | city.sane.wot.ServientConfig | Servient storing credentials for '[]'
20:50:13.043 | main | INFO  | city.sane.wot.Servient | Start Servient
20:50:13.045 | main | INFO  | c.s.w.b.mqtt.MqttProtocolServer | Start MqttServer
20:50:13.050 | ForkJoinPool.commonPool-worker-3 | DEBUG | city.sane.RefCountResource | First Reference. Create Resource.
20:50:13.153 | ForkJoinPool.commonPool-worker-3 | INFO  | c.s.w.b.mqtt.MqttProtocolSettings | MqttClient trying to connect to broker at 'tcp://localhost:1883' with client ID 'wot26692170004867'
20:50:13.475 | ForkJoinPool.commonPool-worker-3 | INFO  | c.s.w.b.mqtt.MqttProtocolSettings | MqttClient connected to broker at 'tcp://localhost:1883'
20:50:13.603 | main | DEBUG | city.sane.wot.thing.ExposedThing | 'null' created
20:50:13.603 | main | DEBUG | city.sane.wot.thing.ExposedThing | 'null' adding Property 'property'
20:50:13.605 | main | WARN  | city.sane.wot.Servient | Servient generating ID for 'ExposedThing{objectType='null', objectContext=null, id='null', title='null', titles=null, description='null', descriptions=null, properties={property=ExposedThingProperty{name='property', state=city.sane.wot.thing.property.PropertyState@79517588, objectType='null', type='string', observable=false, readOnly=false, writeOnly=false, optionalProperties={}, description='null', descriptions=null, forms=[], uriVariables={}}}, actions={}, events={}, forms=[], security=[], securityDefinitions={}, base='null'}'
20:50:13.677 | main | DEBUG | city.sane.wot.thing.ExposedThing | Expose all Interactions and TD for 'urn:uuid:cf86da39-62ae-450e-86bb-9d3fc23c7d50'
20:50:13.677 | main | INFO  | city.sane.wot.Servient | Servient exposing 'urn:uuid:cf86da39-62ae-450e-86bb-9d3fc23c7d50'
20:50:13.679 | main | INFO  | c.s.w.b.mqtt.MqttProtocolServer | MqttServer exposes 'urn:uuid:cf86da39-62ae-450e-86bb-9d3fc23c7d50' at 'mqtt://localhost:1883/urn:uuid:cf86da39-62ae-450e-86bb-9d3fc23c7d50/*'
20:50:13.702 | main | DEBUG | c.s.w.b.mqtt.MqttProtocolServer | Assign 'mqtt://localhost:1883/urn:uuid:cf86da39-62ae-450e-86bb-9d3fc23c7d50/properties/property' to Property 'property'
20:50:13.703 | main | DEBUG | c.s.w.b.mqtt.MqttProtocolServer | Publish 'urn:uuid:cf86da39-62ae-450e-86bb-9d3fc23c7d50' Thing Description to topic 'urn:uuid:cf86da39-62ae-450e-86bb-9d3fc23c7d50'
20:50:13.782 | main | DEBUG | city.sane.wot.content.ContentManager | Content serializing to 'application/json'
20:50:13.789 | main | DEBUG | city.sane.wot.thing.ExposedThing | TD has changed. Inform observers.
20:50:13.790 | main | INFO  | city.sane.wot.Servient | Stop Servient
20:50:13.791 | main | INFO  | c.s.w.b.mqtt.MqttProtocolServer | Stop MqttServer
20:50:13.792 | main | DEBUG | c.s.w.t.p.ExposedThingProperty | 'urn:uuid:cf86da39-62ae-450e-86bb-9d3fc23c7d50' sets Property 'property' to internal value 'example'
20:50:13.792 | main | DEBUG | city.sane.wot.content.ContentManager | Content serializing to 'application/json'
20:50:13.793 | main | WARN  | c.s.w.b.mqtt.MqttProtocolServer | MqttServer cannot publish data for topic 'urn:uuid:cf86da39-62ae-450e-86bb-9d3fc23c7d50/properties/property': null
20:50:13.792 | ForkJoinPool.commonPool-worker-3 | DEBUG | city.sane.RefCountResource | No more References. Cleanup Resource: Pair{first=city.sane.wot.binding.mqtt.MqttProtocolSettings@294ac33b, second=org.eclipse.paho.client.
There are two problems: 1. Retained message with Thing Description for `urn:uuid:cf86da39-62ae-450e-86bb-9d3fc23c7d50` wasn't cleared as it would be if one invokes `ExposedThing:destroy`. 2. Thing's internal subscriptions in `MqttProtocolServer` weren't disposed, so `ThingProperty::write` causes `NullPointerException` on the following line:https://github.com/sane-city/wot-servient/blob/490d03304cfb8b95a9a38e866016fa316ff7541d/wot-servient-binding-mqtt/src/main/java/city/sane/wot/binding/mqtt/MqttProtocolServer.java#L160.