Hello!
So one thing that is not directly obvious is the leshan's LwM2mModel class. This class outlines the objects and resources that (in this case) the leshan-client will initialize with ObjectInitializer. It is also used by ObjectInitializer.createMandatory() which crawls through the LwM2mModel looking for objects with mandatory == true and ObjectInitializer.create(...) which crawls the model looking for the correct definition (in your case 3201). Using the default constructor of ObjectInitializer, it loads only the mandatory objects from the LWM2M specification from the oma-objects-spec.json. As object 3201 isn't in there neither of the create methods on ObjectInitializer will build it.
In the short-term: as you want to create a LwM2mModel including the L2M2M specification and your custom object (3201), you can execute ObjectLoader.loadDefault() returning a List<ObjectModel>, add those to a Map along with your own ObjectModel (for 3201), and create a new LwM2mModel using the LwM2mModel(Map<Integer, ObjectModel> objectModels) constructor. Finally construct ObjectInitializer with this LwM2mModel.
You can now execute createMandatory() and create(3201) (note: you'll probably want to join these lists to pass them into the LeshanClient constructor).
In the long-term: it might be worthwhile to simplify the above sequence. I could see other devs running into similar issues as yourself. It might be more useful to extend ObjectInitializer.setClassForObject() to also take an ObjectModel that would then append to the LwM2mModel member. It would reduce the number of initialization steps as above in the short-term. And Leshan is always looking for contributions! So if you find the time to make a branch and come up with improvements, shoot out a PR (
https://github.com/eclipse/leshan/blob/master/CONTRIBUTING.md)! :)
Hope that was helpful,
-JF