jvermillard / leshan

OMA Lightweight M2M java implementation - LWM2M
40 stars 25 forks source link

Reuse more classes between server and client #61

Closed sbernard31 closed 9 years ago

sbernard31 commented 9 years ago

We need to refactor the code to reuse more classes between client and server.

sbernard31 commented 9 years ago

I think the first classes, we must reuse is LwM2mRequest and LwM2mResponse hierachy. So, I create a branch. The first commit aims to move request from server to core. I had to remove the Client dependencies of LwM2mRequest.

sbernard31 commented 9 years ago

I integrate this commit in master, to be able to do the initial contribution refactoring.

jschloman commented 9 years ago

This looks good (along with the other work refactoring us to a more common core). I apologize for my recent unresponsiveness (business travel, etc) but I'll continue to keep an eye on this work. :)

sbernard31 commented 9 years ago

The next thing I would like to do is to reuse those classes in client. But currently, there are a concept in the client which does not exist at server side : LwM2mExchange. I think we could remove this and just work with LwM2mRequest and LwM2mResponse. (as we do with RegistrationHandler @jschloman, @joshlarson, have you some objections ?

joshlarson commented 9 years ago

I have no objection.

I've been doing a lot of deep thinking about the LwM2mExchange object, which I originally introduced as sort of a parallel to Californium's CoapExchange object. I've since formed the opinion that that was a mistake, since it leads a lot of very complicated aggregator logic.

I think the best approach would be to have the various nodes simply return their values - something like:

public LwM2mResponse<Type> read() {
    return value;
}

Rather than the current

public void read(LwM2mExchange xc) {
    xc.respond(value);
}
jschloman commented 9 years ago

I have no objections and I think the end goal is really good. If I remember there were a couple of places where some thought was going to be required to remove the LwM2mExchange object (sadly my memory is not what it used to be :P ). Hopefully it's a clear place to do the refactors.

sbernard31 commented 9 years ago

I start the refactoring (the big commit is b9aab9d) I reuse request and response at client side for uplink request for now (register, deregister, update, bootstrap) I try to do something which looks like at downlink request management at server side.

1) I see that some code about californium should be shared between client and server side. Does it mean we should create a leshan-core-cf ?

2) For now, I remove parameters validation in CoapClientRequestBuilder, maybe instead of doing some parameters validation here, we should just not allow to create an invalid request ?

3)There're no more timeout on request. So for now there are just a timeout by default, but we should reintroduce a way to set timeout when we send requests. We need this at server side too. Maybe we could add the timeout on send(request) function ?

4) I delete the IdentifierBuilder, I propably missed something, but I could not find its utility and if I keep it the code is really more complex.

5) OperationResponse was replaced by LwM2mResponse, so there're no more isSuccess method but the idea seems good and we should reintroduce it.

6) Currently, we use the word "registrationID" in register,update,deregister. I think we should use the "location" word to be more consistent with the LwM2m specification.

jschloman commented 9 years ago

Looks good :) As for your comments:

1) I think that sounds good and like the server-side, separation between the LWM2M and CoAP layers should be considered at some time. I know that @joshlarson has some opinions on that through talks I've had with him.

2) That seems appropriate. It was originally done as we were adding in support as we did it in piecemeal. As support grows (e.g., we implement queueing mode) we can then update the request signatures to support the ability to do so.

3) I agree. Probably the client is in the best position to determine what sort of timeouts it would like to have and giving them the freedom to do so would probably be appreciated :)

4 and 6) The idea here was to avoid having the "location" simply be a String, which is ambiguous and can lead to a dev to using the lib incorrectly(say an Update request without first doing a Register to get a location). ClientIdentifier was an attempt to do that. Changing it to Location sounds good as, like you said, aligns it with the language in the specification. But I'd still push for it being a Location class over a String just to make the relationship of the Request/Responses clear.

5) I too agree this is useful. It makes the code more functional and gives the behavior a clear path for use by a dev.

Again, I think this work is very cool and making for a nice slimmer cleaner project :)

-JF

sbernard31 commented 9 years ago

I removed the LwM2mExhange hierarchy, in the way @joshlarson proposed. This was not so easy ... I probably introduced a lot of new bugs :p. The good news : the LeshanClientExample works well now with standalone, no more problem with data encoding (TLV/Text). The bad news : the integrations tests are not ok anymore, but before to fix it, I think it could be easier to finished the refactoring.

There are still some classes which are really similar like : LwM2mClientObjectDefinition <-> ObjectSpec LwM2mClientResourceDefinition <-> ResourceSpec and LwM2mClientNode <-> LwM2mNode LwM2mClientObject <-> LwM2mObject LwM2mClientObjectInstance <-> LwM2mObjectInstance LwM2mClientResource <-> LwM2mResource This make the code a bit confusing but I can not find a good way to resolve this problem.

The *Spec and *Definition hierarchies are near the same, the main difference is that LwM2mClientResourceDefinition is able to create a LwM2mClientResource. Maybe we should separate the specification/definition role from the "instance creator" role ? but this mean we should think about another API for the client ?

For the LwM2mClientNode vs LwM2mNode, maybe this is just a naming problem ? The first one has the responsibility to handle request like read/write/create/delete ... and the other one is a data structure. but this kind of code is a bit strange :

public CreateResponse createInstance(LwM2mNode node) {
    ...
    LwM2mObjectInstance instanceNode = (LwM2mObjectInstance) node;
final LwM2mClientObjectInstance instance = new LwM2mClientObjectInstance(instanceNode.getId(), this, definition);
    instance.createMandatory();
    LwM2mResponse response = instance.write(instanceNode);
   ....
mrinalsharma commented 9 years ago

Is there any Impact to external API's

sbernard31 commented 9 years ago

Yes external API is impacted, as LwM2mExchange was exposed via LwM2mClientNode hierarchy.

mrinalsharma commented 9 years ago

Do you have the API locked down? Is it possible to share it? Thanks,Mrinal

ghost commented 9 years ago

I also would like to see the new API because I have to adjust it for the upcoming client builder...

sbernard31 commented 9 years ago

@mrinalsharma, @alex-ellwein the API is not locked down. The project is really young and the API will probably change often. All the current changes is available in the branch clieantrefactoring. And all the discussions is here in this topic.

If you have some idea, please share it here. @alex-ellwein where could we see the API of your client builder ?

ghost commented 9 years ago

The client builder API is still under construction and not ready for public yet, the basic idea is roughly like this:

LwM2mClientBuilder clientBuilder = new LwM2mClientBuilder();
LwM2mClient client = clientBuilder.
         addSingleInstanceObjectDefinition(isMandatory).
        //or addMultiInstanceObjectDefinition(isMandatory).
        .withObjectId(...)  //for multi-inst path: .andInstanceId(...)
        .addSingleResourceDefinition(isReadOnly, isMandatory) 
      //or .addMultipleResourceDefiniton(isReadOnly, isMandatory)
      .withResourceId(...)
      //one of: .andStringValue() || .andBooleanValue() || andIntegerValue()...
      // here i had the idea to use alternatively andStringResource(Lwm2mStringResource) etc.
     .build()

The idea is to provide "a typesafe path", for instance, if one specifies addMultipleInstanceDefinition(), then it would return method withInstanceId(...) so you won't forget anything mandatory for that particular definition. But as I said, it is under construction and may change.

jschloman commented 9 years ago

Simon,

Glad to see it coming together! For the LwM2mClientNode <-> LwM2mNode issue, I know that there were attempts to find the right way to do this while we went through the specification implementing it. The casting and other stuff is probably a result of that. Doing a different separation of the data structure elements from the creation/behavior work using different patterns might clean it up. Sadly these sort of problems seem to be solved by doing it and seeing if the finished product is an improvement.

For the definition-instance creation API stuff I think that's a big question: how easy/intuitive/useful is the current client API for building a heterogenous ecosystem of devices or is there an easier way of doing it? Right now the example client mostly does single resources and not many multiples. I could see if a device wanted to do more of the latter a separate creator object from the definition could be desirable.

Hmm, dunno if any of what I wrote was helpful. But it looks like its great work here with a lot of nice improvements (I especially like the TimeResource with the Timer in it in the example. It shows more ways for devs to use the library :smiley: ).

sbernard31 commented 9 years ago

I tried to fix the problems I talked about in this previous comment. And little by little, I go to this new API / implementation ... : I commit this in a new branch newclientapi as it was just a proposition.

I introduce a LwM2mObjectEnabler interface which aims to limit the contract to plug new CoAP implementation (or even other transport layer). You could see the californium implementation as example.

I introduce a new API too for initialize resouces tree, with a kind of builder : ObjectsInitializer

// This will create a list of ObjectEnabler for all the
//  mandatory object with a default stupid behavior.
List<ObjectEnabler> enablers = initializer.createMandatory();

// You could also say, I want object 2,3,4 and 7 in my resource tree.
List<ObjectEnabler> enablers = initializer.create(2,3,4,7);

// The default stupid object is not so bad to test,
//  but in the real life you want your own implementation.

// E.g. the line below means that 
// Device class will be used for instance of object 3 and default one for others.
// The Device class must implement LwM2mInstanceEnabler interface and have
//  a constructor without parameter.
initializer.setClassForObject(3, Device.class);   
List<ObjectEnabler> enablers = initializer.create(2,3,4,7);

// then you create your client
LeshanClient client = new LeshanClient
(clientAddress, serverAddress, new ArrayList<LwM2mObjectEnabler>(enablers));

We could imagine a lot of way to improve the ObjectInitializer, like :

The LwM2mObjectEnabler could also be used for leshan client users who need to implement a complex object and who was limited by the simpler API. The BaseObjectEnabler class could be used too to avoid to rewrite some generic code.

I will wait for feedback before to continue on this way.

jschloman commented 9 years ago

Simon,

I really like this Enabler-Initializer pattern as it really separates the CoAP layer implementation from the client/device-facing specific behavior. And as you say there are a lot of ways to make it cleaner for a developer to build on. When we build the original client the issue of managing object instances (in both single and multiple) is where we found a lot of the difficulty to arise so hopefully the separation between definition, initialization and implementation should make it cleaner (when you mention using reflection, I assume you mean to make the large switch statements that the LeshanClientExample unnecessary?)

Other thoughts:

  1. Is it necessary to pass in a list of enablers to the client constructor and just pass the Initializer? My thinking is that a client should always take the mandatory objects plus the objects the developer has setTheObject()'s on their Initializer. I guess I'm thinking of an evolving code base and removing a possible error step (e.g., adding the Enabler but not creating it when passing to the client constructor).
  2. Might it be better for the LwM2mInstanceEnabler to return a LwM2MResponse (or similar) on the methods? A device could potentially fail (e.g., paper jam) and has no way of sharing that up in a failed operation. In that way SimpleInstanceEnabler could be more like BaseObjectEnabler in that its default behavior is to fail on all operations (and developers have to extend it for behaviors they desire to have).

But it looks good. I'm interested in seeing how it progresses :smile:

-JF

sbernard31 commented 9 years ago

Thx for the feedback ;) For the reflection, yes it was the idea but surely not the priority. (maybe this is even better to generate code and simple interface from spec for standard objects).

  1. My first thought was that initializer is just an helper, and I would not constraint advanced users. This also allow users to create some objects with the initializer and add advanced objects which just implement LwM2mObjectEnabler or BaseObjectEnabler. But as you say this could be error prone.
  2. It cleary missed a way to manage error in the LwM2mInstance interface. I hesitate between return LwM2mReponse or adding exception. It's tempting to do the same thing than BaseObjectEnabler, this could be more consistent, but the two class does not aim the same public. BaseObjectEnabler is for advance user and LwM2mInstance is the common use case. Using exception allow user to raise it in this kind of method instead of returning a LwM2mResponse. I don't know...
jschloman commented 9 years ago

I've really become anti-exception-based execution in my old age :) and have become more partial to a functional/monad style of Try/Optional return types on methods (hence the original OperationResponse in the client) which let us use clean if/else conditionals instead of a battery of catch statements. I know that this sort of thing has gotten to vi vs. emacs level insanity in our offices so I understand that for everyone else YMMV :smile:

sbernard31 commented 9 years ago

2 Ok, we could start with the LwM2mReponse.

sbernard31 commented 9 years ago

I think it could be nice to integrate this in master now ?

ghost commented 9 years ago

Wow, nice work, Simon. I especially appreciate that now the objects can be initialized from a JSON file... It seems that now my proposed fluent client API is not needed anymore, but i also like your approach much better. Great stuff.

jschloman commented 9 years ago

OK so I apologize for how long it's taken so long for me to reply to this but I also wanted to go through all the work here and not just a superficial response :)

  1. Responses look good. Obvious cut point for where the Bootstrap work will need to go.
    • I think a near-term step would be to decide on how to handle failures (that server could cause a ResourceAccessException on the device might not be the most desirable to users when dealing with a Response). Again I'd recommend some Monad like Optional or the previous OperationResponse. With the common server/client this possibly could be a bigger discussion the group would need to have.
    • Also allowing devices themselves to issue up some type of failure other than a BAD_REQUEST (e.g., ObjectEnabler.doCreate() where it says it's "not really a bad request")... it's out of spec... so is this a recommendation we push up to the OMA? Or do we have a work around in Leshan?
  2. Possibly move SimpleInstanceEnabler to the leshan-client-example as it is an example of an implementation? Or do we view this as being more core? If so, should we add this into BaseInstanceEnabler?
  3. Observation/Write Attributes
    • I guess we need to decide what needs to implemented the Information Reporting Interface. Do we want to have the client library actually manage the observations on the client (this was the direction we originally went with the first iteration of the client)? This would probably be useful as its logic that would be common for all LWM2M clients... but it is also a big execution thing to tackle. I've always felt that Obervations were one of the killer features of LWM2M so doing this would be very useful.
    • And your TODO about trying to work with Californium better on its existing management of ObserveRelations would be good. I could see that being very useful for other Californium-based tools, not just Leshan :)
  4. I think the observation stuff also relates to what you discuss on line 42 of ObjectEnabler in deciding what the best way to do thread-safe management of these resources in the library would be.
  5. A quick unit test thing: the ObserveTest.can_observe_resource() test does not consistently pass. It might be worthwile to add in an Awaitility wait there or something to receive the notify.

I guess the final thing is what do you feel the next highest priority improvements would be? Obviously the original thrust of this was to introduce commonality between client and server (and fix the inability to do reads on Object Instances) and there are a lot of good TODOs in there. I see in ObjectResource that there is still TODOs about increasing commonality with the WriteRequest and how the LinkFormat stuff shouldn't be in there. Maybe the next step would be to do this next level of refactor?

Regardless I think this is really good work! :)

-JF

sbernard31 commented 9 years ago

Thx alex and josh for your feedbacks.

  1. I agree, we need a good way to manage failure (at server and client side). This is crazy, but this is currently out of spec oO ... I open an issue at OMA. Waiting we probably need a short term solution. For now, we return BAD_REQUEST ... But we could discuss about that in an other thread on the mailing list for example.
  2. SimpleInstanceEnabler is used in example and in integration tests. I think this class should be not used in production but this is a good way to start quickly. For now, I think we should keep it in core. BaseInstanceEnabler should be reused. All of this need javadoc :D 3/4. For the observation/write attrbutes, I'm ok this is something we should provide in leshan as it should be common for all device. But as you said this seems to be a big part, I prefer finalize some others stuff before to attack this one. (but if someone would start some works in a branch, I will follow this)
  3. We need to fix that, I would like to run integration-tests in hudson as soon as possible.

For the near future: a) I agree, to clean the objectResource class sounds good. Particularly the WriteRequest and linkformat TODO. b) I would also like to separate client in 2 project the client-core and client-cf. c) Manu and Me worked about the possibility to have a model by device at server side. I would like to implement some stuff about this and discover at client side.

I will probably integrate this refactoring in master before the end of the week (if there is no objection). After that I could restart on more little modification. Whew!

jschloman commented 9 years ago

Cool cool! Yeah I think going forward with pushing this into master on Eclipse is good. :smiley: I hope that in the next few weeks we should be able to start jumping back into contributing too.

-JF

sbernard31 commented 9 years ago

This is integrated in master.

mrinalsharma commented 9 years ago

Hello, This is really good work. Personally, I am interested in seeing how I can updated Object Instance and notify to Server. Is it also implemented in this change and is there an example you can share? Thanks,Mrinal

sbernard31 commented 9 years ago

Hi Mrinal, If you want to notify that a resource change you should use this method fireResourceChange of BaseInstanceEnabler. This will send a notify to the server if this one request for observation on this resource. You could see an example in LeshanClientExample

ghost commented 9 years ago

Seems that the client has the same issue as the wakaama client had recently :) It provides at the registration a list of object links with object IDs (although an instance ID must be given for an existing object, as referred in specs). For instance, try to create a mandatory object Device (ID 3), then it provides </3> at registration time, not </3/0> as it should.

sbernard31 commented 9 years ago

Thx, the object links for register and discover is cleary in a bad state :p. I want to finish to write some tests about security (PSK, RPK) and I will focus on that !

ghost commented 9 years ago

It would be great to have writeAttributes() and observe() in the LwM2mInstanceEnabler

sbernard31 commented 9 years ago

I didn't thought about this a lot but, I feel it is possible to implement this at BaseObjectEnabler level.

jschloman commented 9 years ago

So looking at Bootstrap yesterday I found that we might need to reintroduce the setting of the Californium MessageDeliverer. But if that is to be done I guess I was wondering what the approach would be? We originally did it as a Create on an ObjectInstance will fail in the deliverRequest method because the Californium CoapResource for it doesn't exist. We planned to have Objects/Object Instances/Resources all as CoapResources under it's RootResource that Californium would deliver to.

Or would the idea be to just have ObjectResource as the only CoapResources and have it handle the requests to its children? It might make the creation of new ObjectInstances easier. There is also the issue of how to handle Writes in the Bootstrap sequence: section 8.2.2 says

Different from „Write“ operation in Device Management and Service Enablement interface, the LWM2M Client MUST write the value included in the payload regardless of an existence of the targeting Object Instance or Resource.

So that's another behavior that would require trickiness in the MessageDeliverer... and it should only be available during Bootstrap (so there need for new state in the LeshanClient that tells it if this is valid or not. Maybe it gets set depending on when requests are sent? So it's only valid between a BootstrapRequest and a RegisterRequest?). I guess I wanted to ask what the consensus best approach would be before doing a bunch of cutting :smiley: (Also, I wasn't sure if this is a good place to put this comment or if I should do it on the eclipse github... or on the dev mailing list? I guess I wanted to be careful about dropping more stuff on Julien's github :smile: )

sbernard31 commented 9 years ago

I'm not sure to fully understand but in my point of view we should try to have a CoAP Resource by LwM2m object. (LwM2m instance and LwM2M resource doest not get their own CoAP Resource). This simplify a lot the implementation and make the transport layer abstraction easier.

To do that we must have a CoAP resource which receive all the request under a given path. (/3, /3/0, 3/0/1 should be sent to the CoAP Resouce which handle the object 3)

This is currently implemented in ObjectResource this way. It seems not so clean but I asked to Matthias and that's the good way to do.

So, we don't need a custom Message deliverer for that, I'm right ? (Or maybe I missed something ^^)

For the bootstrap problem, the spec is a bit strange, an issue is open here. But I don't see how a message deliverer could help to resolve this issue ?

(You right we should have all those discussions on the mailing list :p, but maybe if we continue here we can beat the record of the longest github issue :p)

jschloman commented 9 years ago

Re: longest github issue... LOL, now that's something to demo at EclipseCon Europe! :laughing:

Yeah the MessageDeliverer is where the work is done for the path stuff for all of the requests. A /3 will get to the ObjectResource with 3 as its Id but even if the ObjectResource can handle creates on /3/0, it won't get to the resource as the default ServerMessageDeliverer will not find a valid CoapResource for that path and just returns a 4.04.

Also the default Californium ServerMessageDeliverer has a lot of private members that need to be accessed so right now the wayforward for us is to just duplicate ServerMessageDeliverer, set it via setMessageDeliverer() and alter the small amount of behavior we need. I too talked to Matthias about this at EclipseCon and he was open to suggestions to make the interface for Californium easier.

Either way this is where a Bootstrap Write from the server would have to be passed to the correct ObjectInstance and it would have to handle the current awkward Write on uncreated Instances/Resources (until/unless OMA changes that behavior :smiley: : ).

mrinalsharma commented 9 years ago

So, this method can update Instance(e.g  3\0)?  I want to notify about the instance change to Server rather than the individual resource of an object. Thanks,Mrinal

sbernard31 commented 9 years ago

@mrinalsharma, this is not implemented for now. But I imagine, we could implement it in a way that if you do fireResourceChange on a given resource and if server asked for an observe on the whole instance, it would be notified.

sbernard31 commented 9 years ago

@jschloman, Maybe I misunderstanded your point (I confess my english is not so good :/)

but, what I try to explain is that this code in ObjectResource (which implements CoapResource):

   @Override
    public Resource getChild(String name) {
        return this;
    }

do exactly what you want without the need to implement your own ServerMessageDeliverer.

Currenlty, there is only one java instance of ObjectResource for the object 3 and it will receive /3, /3/0 and /3/0/1 requests.

jschloman commented 9 years ago

@sbernard31

So I've been looking at the issue deeper and yes the return this; works in all cases... except when the Bootstrap server sends a DELETE on '/'... which goes to the Californium RootResource, which is a private inner class which returns a failure response. One short-term solution would be to create a LeshanRootResource and have it be the only child under the Californium RootResource (this could also allow us to not actually delete mandatory object instances, etc). ObjectResources would then be children of the LeshanRootResource.

But as a part of a larger discussion on commonizing code: I've been looking at implementing Bootstrap (in particular client-initiated Bootstrap) and I realized I should probably sync here before going forward:

  1. If a client is going to support several Servers (of both Bootstrap and Standard variety) the construction of the LeshanClient will probably need to change (which right now only takes one server address). Since these Servers can be set during the Bootstrap phase, it would probably be useful if they were POJOs. I think the BootstrapConfig.ServerConfig and ServerSecurity are good candidates for this (and another case for commonizing :smile: ).
  2. The general use flow:
    • The user would (maybe using a Builder like the LeshanServer?) build their initial object model. This would include the factory-set Server/Security objects.
    • LeshanClient.send() would be modified to take a Server parameter (similar to the LeshanServer.send() taking a Client). This Server would be one of the above Server objects.
    • Internally the LeshanClient would need a map of Servers to Endpoints with the Endpoints configured given the ServerSecurity defined either by the Builder or sent from the Server.
    • When the LeshanClient.send() is called, the RequestBuilder would find the appropriate Endpoint and issue the call from that.
  3. When a new Server is created above, it would be set as either Standard or Bootstrap. From this internally the LeshanClient would assign an ObjectResource (if Standard) or a limited Bootstrap Resource (which would only allow for the Writes and Deletes specified in the spec).
  4. The nice thing about 2 and 3 above is that it builds the groundwork for ACL by limiting what a server can request on a particular Object Instance.

Thoughts? Does this seem to be a good approach? I have gotten "one foot in the water" and wanted avoid jumping in without synching with folks :smiley:

-JF

sbernard31 commented 9 years ago

(Sry for the delayed response) About the root resource, I see there is a createRoot() method on CoAPServer maybe we could override it to create our own RootResource.

  1. You're right we need to change this. But I don't know so much about bootstrap.
  2. I'm ok with the workflow.
    • We could probably use ObjectsInitializer for that.
    • Maybe instead of passing a server object we should just pass server ID.
    • I don't know if we need a map, maybe we could retrieve the endpoint from server ID and Object 0 (lwmM2m security)
    • ok
  3. I not sure to well understand the point ? but this will be clearer when you will show us the code ;).
mrinalsharma commented 9 years ago

Sorry for the late reply..I was on vacation..Can you give me some more pointers on how can I implement it today. In the .10 version of Leshan, I was able to notify on Instance by modifing some code. In .11 version I am not sure how to do it. Functionality in my server code is dependent on Instance Observation. Thanks,Mrinal

 On Monday, March 23, 2015 6:57 AM, sbernard31 <notifications@github.com> wrote:

@mrinalsharma, this is not implemented for now. But I imagine, we could implement it in a way that if you do fireResourceChange on a given resource and if server asked for an observe on the whole instance, it would be notified.— Reply to this email directly or view it on GitHub.

mrinalsharma commented 9 years ago

Is it a good option to add  instance listener from Method "private void listenInstance(LwM2mInstanceEnabler instance, final int instanceId)" of ObjectEnabler.java. When a resource is changed fireInstanceChange() method can execute instanceChanged(). fireInstanceChange() method also need to be coded.

    private void listenInstance(LwM2mInstanceEnabler instance, final int instanceId) { instance.addResourceChangedListener(new ResourceChangedListener() { @Override public void resourceChanged(int resourceId) { getNotifySender().sendNotify(getId() + "/" + instanceId + "/" + resourceId); } }); /*New Code/ instance.addInstanceChangedListener(new InstanceChangedListener() { @Override public void instanceChanged(int instanceId) { getNotifySender().sendNotify(getId() + "/" + instanceId ); } }); }  

 On Friday, April 17, 2015 12:55 AM, mrinal sharma <mrinalsharma@yahoo.com> wrote:

Sorry for the late reply..I was on vacation..Can you give me some more pointers on how can I implement it today. In the .10 version of Leshan, I was able to notify on Instance by modifing some code. In .11 version I am not sure how to do it. Functionality in my server code is dependent on Instance Observation. Thanks,Mrinal

 On Monday, March 23, 2015 6:57 AM, sbernard31 <notifications@github.com> wrote:

@mrinalsharma, this is not implemented for now. But I imagine, we could implement it in a way that if you do fireResourceChange on a given resource and if server asked for an observe on the whole instance, it would be notified.— Reply to this email directly or view it on GitHub.

jschloman commented 9 years ago

I've come to a similar solution recently although with a slightly different approach:

  1. have an InstanceChangedListener with methodology like void onCreate(LwM2mInstanceEnabler newInstance);
  2. Modify the ObjectsInitializer so that it has a constructor that can take a list of InstanceChangedListeners.
  3. In ObjectsInitializer.createInstance() after the instance is created execute private void fireInstanceCreated(final LwM2mInstanceEnabler instance) { for (final InstanceChangedListener l : listeners) { l.onCreate(instance); } }

For me that has been enough to then do further things that may or may not be built into the core of the client. For myself I extended BaseInstanceEnabler with an interceptable version (InterceptInstanceEnabler) that I can add hooks into (when the above onCreate() is called). My device can then do the fireResourceChange() from outside the InstanceEnabler instance (as well as intercept the read/write/executes).

mrinalsharma commented 9 years ago

Thank you for prompt reply..

 On Friday, April 17, 2015 10:26 AM, John <notifications@github.com> wrote:

I've come to a similar solution recently although with a slightly different approach:

  1. have an InstanceChangedListener with methodology like void onCreate(LwM2mInstanceEnabler newInstance);
  2. Modify the ObjectsInitializer so that it has a constructor that can take a list of InstanceChangedListeners.
  3. In ObjectsInitializer.createInstance() after the instance is created execute private void fireInstanceCreated(final LwM2mInstanceEnabler instance) { for (final InstanceChangedListener l : listeners) { l.onCreate(instance); } }For me that has been enough to then do further things that may or may not be built into the core of the client. For myself I extended BaseInstanceEnabler with an interceptable version (InterceptInstanceEnabler) that I can add hooks into (when the above onCreate() is called). My device can then do the fireResourceChange() from outside the InstanceEnabler instance (as well as intercept the read/write/executes).— Reply to this email directly or view it on GitHub.
mrinalsharma commented 9 years ago

Android doesnt support javax.xml.bind.DatatypeConverter. Because of this code in file LwM2mNodeEncoder throws exception when run on Android. Is is possible to use some other package? The exception it throws is class not found.  

 On Friday, April 17, 2015 1:26 PM, mrinal sharma <mrinalsharma@yahoo.com> wrote:

Thank you for prompt reply..

 On Friday, April 17, 2015 10:26 AM, John <notifications@github.com> wrote:

I've come to a similar solution recently although with a slightly different approach:

  1. have an InstanceChangedListener with methodology like void onCreate(LwM2mInstanceEnabler newInstance);
  2. Modify the ObjectsInitializer so that it has a constructor that can take a list of InstanceChangedListeners.
  3. In ObjectsInitializer.createInstance() after the instance is created execute private void fireInstanceCreated(final LwM2mInstanceEnabler instance) { for (final InstanceChangedListener l : listeners) { l.onCreate(instance); } }For me that has been enough to then do further things that may or may not be built into the core of the client. For myself I extended BaseInstanceEnabler with an interceptable version (InterceptInstanceEnabler) that I can add hooks into (when the above onCreate() is called). My device can then do the fireResourceChange() from outside the InstanceEnabler instance (as well as intercept the read/write/executes).— Reply to this email directly or view it on GitHub.
sbernard31 commented 9 years ago

@mrinalsharma the javax.xml.bind.DatatypeConverter issue is not really linked to this thread. Please, for this one open an issue on bugzilla. And more generally open a new issue or a new discution on the mailing list if you don't find a bug or thread about what you want to talk about. (But Thx I think we will succeed to beat the longest issue record on github :D)

mrinalsharma commented 9 years ago

I thought I changed the subject line. Sorry!!

 On Monday, April 27, 2015 11:33 AM, sbernard31 <notifications@github.com> wrote:

@mrinalsharma the javax.xml.bind.DatatypeConverter issue is not really linked to this thread. Please, for this one open an issue on bugzilla. And more generally open a new issue or a new discution on the mailing list if you don't find a bug or thread about what you want to talk about. (But Thx I think we will succeed to beat the longest issue record on github :D)— Reply to this email directly or view it on GitHub.

sbernard31 commented 9 years ago

no problem ;). I think github does not manage the case where you change the subject line. (You reply to the email notification but in fact it's just a github feature to add a comment to this issue : https://github.com/jvermillard/leshan/issues/61)