Bug 488769 - Create Content instance by retargeting from a plugin giving an internal error
Summary: Create Content instance by retargeting from a plugin giving an internal error
Status: REOPENED
Alias: None
Product: OM2M
Classification: IoT
Component: Platform (show other bugs)
Version: unspecified   Edit
Hardware: PC Linux
: P3 major
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-03-01 10:53 EST by EL KIASSE Marouane CLA
Modified: 2016-03-02 06:25 EST (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description EL KIASSE Marouane CLA 2016-03-01 10:53:57 EST
Hi,

I tried to create a Content Instance resource from "in" to "mn" using retargeting.

I sent the request [doRequest(request)] from a plugin developed in the "in".


Code used for creating CIN Resource 
ContentInstance contentInstance = new ContentInstance();
contentInstance.setContent("xml obix");
contentInstance.setContentInfo(MimeMediaType.OBIX);

I got this internal error in "in" :


[ERROR] - org.eclipse.om2m.core.comm.RestClient  
RestClient error
java.lang.ClassCastException: org.eclipse.om2m.commons.resource.ContentInstance cannot be cast to java.lang.String
	at org.eclipse.om2m.binding.http.RestHttpClient.sendRequest(RestHttpClient.java:120)
	at org.eclipse.om2m.core.comm.RestClient.sendRequest(RestClient.java:60)
	at org.eclipse.om2m.core.redirector.Redirector.retarget(Redirector.java:102)
	at org.eclipse.om2m.core.router.Router.doRequest(Router.java:153)
	at org.eclipse.om2m.plugin.util.RequestSender.createResource(RequestSender.java:54)
	at org.eclipse.om2m.plugin.util.RequestSender.createContentInstance(RequestSender.java:66)

The problem comes of RestHttpClient which tries cast ContentInstance to String

Is this a bug or I Am missing something ?

PS: I tried to create a content instance with postman by retarting, it works.
Because I think that in this case the body is not transformed as a resource in the "in". 

Thanks
Comment 1 Francois Aissaoui CLA 2016-03-02 04:11:56 EST
Hello,

This is a normal behavior because the RestClient service waits for a String payload and not a Java Object. 

So you need to use the DataMappingService to serialize the content instance to a String. You only need to retrieve the service in the same way as the CseService and use the method to map the java object to a string. Then, you have to put it as the content in the RequestPrimitive object. 
Also, you have to specify the requestContentType parameter in the request corresponding to "application/xml". You can use the constant available on MimeMediaType.XML from the commons plugin. 

Hope this can help,
François
Comment 2 EL KIASSE Marouane CLA 2016-03-02 05:12:18 EST
Hi François,

Ok, thank you for your explanation.

Here is the code of serialization perhaps can help somebody

String resource = DataMapperSelector.getDataMapperList().get(MimeMediaType.XML).objToString(contentInstance);

// Import : import org.eclipse.om2m.core.datamapper.DataMapperSelector;

	
Furthermore, why om2m do not manage this problem and abstract this feature ?
The developer address the local or remote cse with the same manner.


Bests regards

Marouane
Comment 3 Francois Aissaoui CLA 2016-03-02 05:32:56 EST
Hi Marouane,

If you are working inside the core plugin, this works. If not, you should not use (and even import) packages from the core plugin (you still have to import the org.eclipse.om2m.core.service has this has the interface for the CseService). This is not a good use of the OSGi framework. Instead, you should try to retrieve the OSGi service using a ServiceTracker on the DataMappingService class. 

For the question of abstraction, this is difficult to handle as the platform is able to handle multiple data exchange format. So, inside the content attribute in RequestPrimitive, you can have multiple type of objects (Resource object, String, oBIX). 
If we want to make the abstraction, we have to know 2 parameters, the current type of the content attribute and the type you want at the end for the request. As the RequestPrimitive is already a complex object, it is difficult to make the user have so much parameters to set for a simple format handling. 

So, in your code, you just need to check if you are currently sending a request to your current CSE, then you can use java object. Or, if you want to store information on another CSE, you know that you will have a communication so you can handle this in you IPE / plugin. 

In a nutshell, it would be a really complex mechanism, for the platform AND the user to make this abstraction and we think that it is not necessary as the user has a simple check to make when he builds his request.

Hope this gives you an highlight of our choices,
Best regards,
François
Comment 4 Mahdi Ben Alaya CLA 2016-03-02 06:24:04 EST
Dear Marouane and François, 

First, thank you for your this nice discussion.

In the SmartM2M version of OM2M we accept both requests. In fact, we have in the router an implementation of two "doRequest" methods in order simplify the life of developers:

- The first method accepts a normal requestIndication with a String representation:
doRequest(Requestindication requestIndication )

- The second method accepts separate parameters including a Resource object representation:
doRequest(String method, String targetID,String requestingEntity, Resource resource)

Implementation of the second "doRequest" method:
public ResponseConfirm doRequest(String method, String targetID,String requestingEntity, Resource resource ){
        // Convert the resource object to an xml String
        String representation = null;
        if(resource!=null){
            representation = XmlMapper.getInstance().objectToXml(resource);
        }
        // Create a RequestIndication object
        RequestIndication requestIndication = new RequestIndication(method, targetID, requestingEntity, representation);
        // Call doRequest method and return the received response.
        return doRequest(requestIndication);
}

As you can see here the second "doRequest" method takes only the Resource object from the developer and do the conversion for him (objectToXml), then a requestionIndication Object is seamlessly created and passed to the first "doRequest" method.

François is right that the second "doRequest" method is not exposed by the router in the CORE service plugin which is not good based on an OSGi perspective. So, maybe a second "doRequest" method supporting objects can be exposed for locally deployed plugins especially that all resources classes are available in the commons plugin.

Mahdi