+ Start a Discussion
sergii poluektovsergii poluektov 

OData4: Salesforce sets id to '/x' when retrieving an external object.

Hi everyone,
I am now trying to build an OData 4 service so that Salesforce can access the external data.
So far I was able to get the list view of the external objects with pagination. However when I am trying to access a particular object
I get an HTTP error "400 Bad request". When I inspect the used URL I see that the key property "id" is set to '/x' (%2Fx if encoded) instead of the real id, which can even be seen in the list view.
Here is the decoded URL: https://ecme.empolis.com/oauth/LegoService/LegoService.svc/events?$top=2&$filter=id eq '%2Fx'&$count=true&$select=description,id,sensorId,severity,timestamp,unitId,value
I tried some sample oData4 services provided by odata.org and there the key property is set to its actial value in the same situation.
What can be the reason? How can I fix it?

 
pconpcon
You're not the only one that's hitting this issue.  I just tried it out in my sandbox and I get the same failure.  The good(ish) news is that it seems to only be related to how the individual object page is generated and not to the OData Connector.  I'm able to use the Query Editor and do queries against the data and it returns correctly.  I've reached out to some of my contacts to see if they can help me track someone down.  I'll keep you updated.

In the mean-time, you could always write a custom VF page that pulls the data via SOQL and pushes it out to the page.
Pat PattersonPat Patterson
I passed this on to the product team - they're investigating right now. Please file a case - if it is a bug on our end, this will help to prioritize the fix.
sergii poluektovsergii poluektov
Thanks for the support. I hope the issue will be found.
Pat PattersonPat Patterson
There are a couple of issues here:
  • Your service seems to be responding with 400 because of the '+' signs in the $filter query param. This seems to be a common bug in OData services. '+' is allowed as an encoding of space (' ') - check out this query against the OData reference service (http://services.odata.org/V4/Northwind/Northwind.svc/Products?$filter=UnitPrice+gt+60). Replacing '+' with '%20' seems to allow the request to be processed better.
  • We are passing '%2Fx' as the id. I'm still investigating why this is happening.
sergii poluektovsergii poluektov
Hi Pat,

thanks for the reply.
Here are some thoughts that may help finding the issue:
  • My OData service cannot answer to a request with "metadata=full" accept header. It is programmed with the olingo library, which seems to have problems with it. That's why I am also not able to use the json format in the external data source settings. 
  • The link elements of the entries are not set explicitely as a part of the response. So on the page where the list of external objects is shown the display URL looks for example like this "http://AVBxpAK97MSDC4DC0WRA", where AVBxpAK97MSDC4DC0WRA is the id. However I don't think that this is the problem because the URL to an individual entry page when using the Northwind service and when using my service are identical: https://emea.salesforce.com/x/Customers__x/ALFKI vs. https://emea.salesforce.com/x/events__x/AVBxpAK97MSDC4DC0WRA

 
Pat PattersonPat Patterson
Hi Sergli - Not sure where to go with this - one of our engineers was taking a look at it, but https://ecme.empolis.com/oauth/LegoService/LegoService.svc/events is no longer working - it returns a 500 error. Let me know when it's stable again and we can take another look.
sergii poluektovsergii poluektov
Hi Pat. The server is now working and I ll keep an eye on it to prevent long downtimes.
It would be great if someone could look at it one more time. 
Pat PattersonPat Patterson
Hi Sergii,

Looking at an event (from https://ecme.empolis.com/oauth/LegoService/LegoService.svc/events), I don't think there's enough detail here for us to retrieve an individual event:
<a:feed xmlns:a="http://www.w3.org/2005/Atom" xmlns:m="http://docs.oasis-open.org/odata/ns/metadata" xmlns:d="http://docs.oasis-open.org/odata/ns/data" m:context="$metadata#events">
  <a:id>
    http://10.12.86.21:8080/LegoService/LegoService.svc/events
  </a:id>
  <a:entry>
    <a:id>AVCqmenbMGipdmTLFABN</a:id>
    <a:title/>
    <a:summary/>
    <a:updated>2015-11-02T22:55:13Z</a:updated>
    <a:author>
      <a:name/>
    </a:author>
    <a:link rel="edit" href="AVCqmenbMGipdmTLFABN"/>
    <a:category scheme="http://docs.oasis-open.org/odata/ns/scheme" term="#oData.lego.raw"/>
    <a:content type="application/xml">
      <m:properties>
        <d:id>AVCqmenbMGipdmTLFABN</d:id>
        <d:timestamp m:type="DateTimeOffset">2014-02-25T15:45:35.955Z</d:timestamp>
        <d:signal>motor2</d:signal>
        <d:value m:type="Double">-1.0</d:value>
        <d:severity>NOTICE</d:severity>
        <d:unit>DUMPER</d:unit>
        <d:description>MOTOR OFF</d:description>
      </m:properties>
    </a:content>
  </a:entry>
  ...
</a:feed>
In my sample Olingo OData 2.0 database, id is an absolute URL for the entry record, and link is relative to the entity set url. From http://orderdb.herokuapp.com/orders.svc/Orders/
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xml:base="http://orderdb.herokuapp.com:80/orders.svc/">
  <id>http://orderdb.herokuapp.com:80/orders.svc/Orders</id>
  <title type="text">Orders</title>
  <updated>2015-11-02T20:21:28.303Z</updated>
  <author>
    <name/>
  </author>
  <link href="Orders" rel="self" title="Orders"/>
  <entry>
    <id>
      http://orderdb.herokuapp.com:80/orders.svc/Orders(1002)
    </id>
    <title type="text">Orders</title>
    <updated>2015-11-02T19:55:55.267Z</updated>
    <category term="default.Order" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
    <link href="Orders(1002)" rel="edit" title="Order"/>
    <content type="application/xml">
      <m:properties>
        <d:customerID>5</d:customerID>
        <d:orderDate>2014-02-15T00:00:00</d:orderDate>
        <d:orderID>1002</d:orderID>
        <d:shippedDate>2014-02-18T00:00:00</d:shippedDate>
      </m:properties>
    </content>
  </entry>
  ...
</feed>
GET on http://orderdb.herokuapp.com:80/orders.svc/Orders(1002) returns just that entry, as expected:
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xml:base="http://orderdb.herokuapp.com:80/orders.svc/">
  <id>
    http://orderdb.herokuapp.com:80/orders.svc/Orders(1002)
  </id>
  <title type="text">Orders</title>
  <updated>2015-11-02T20:06:45.347Z</updated>
  <category term="default.Order" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
  <link href="Orders(1002)" rel="edit" title="Order"/>
  <content type="application/xml">
    <m:properties>
      <d:customerID>5</d:customerID>
      <d:orderDate>2014-02-15T00:00:00</d:orderDate>
      <d:orderID>1002</d:orderID>
      <d:shippedDate>2014-02-18T00:00:00</d:shippedDate>
    </m:properties>
  </content>
</entry>
I've been unable to figure out the corresponding query to get a single event record from your service. I tried https://ecme.empolis.com/oauth/LegoService/LegoService.svc/events(AVCqmenbMGipdmTLFABN) , but it gives an error: "The key value 'AVCqmenbMGipdmTLFABN' is invalid." I also tried https://ecme.empolis.com/oauth/LegoService/LegoService.svc/events/AVCqmenbMGipdmTLFABN , but got "The property 'AVCqmenbMGipdmTLFABN' must not follow a collection."

I'm not an expert on the OData 4.0 spec, but, looking at this, I think you need a URL per event record, and to supply that URL in the id field.
sergii poluektovsergii poluektov
Hi Pat,
following your advice I have implemented the retrieval of the individual elements with queries like
http://orderdb.herokuapp.com:80/orders.svc/Orders(1002)
In my case it is https://ecme.empolis.com/oauth/LegoService/LegoService.svc/events('1') which gives
<entry context="$metadata#events">
    <id>events('1')</id>
    <title/>
    <summary/>
    <updated>2015-11-03T19:56:04Z</updated>
    <author>
        <name/>
    </author>
    <link rel="edit" href="events('1')"/>
    <category scheme="http://docs.oasis-open.org/odata/ns/scheme" term="#oData.lego.raw"/>
    <content type="application/xml">
    <properties>
        <id>1</id>
        <timestamp type="DateTimeOffset">2014-02-25T15:45:35.955Z</timestamp>
        <signal>motor2</signal>
        <value type="Double">-1.0</value>
        <severity>NOTICE</severity>
        <unit>DUMPER</unit>
        <description>MOTOR OFF</description>
    </properties>
</content>
</entry>
Then I also specify the full URL to the individual elements in the id attribute
<feed context="$metadata#events">
    <id>http://10.12.86.21:8080/LegoService/LegoService.svc/events</id>
    <entry>
        <id>https://ecme.empolis.com/oauth/LegoService/LegoService.svc/events('1')</id>
        <title/>
        <summary/>
        <updated>2015-11-03T20:02:04Z</updated>
        <author>
            <name/>
        </author>
        <link rel="edit" href="https://ecme.empolis.com/oauth/LegoService/LegoService.svc/events('1')"/>
        <category scheme="http://docs.oasis-open.org/odata/ns/scheme" term="#oData.lego.raw"/>
        <content type="application/xml">
        <properties>
            <id>1</id>
            <timestamp type="DateTimeOffset">2014-02-25T15:45:35.955Z</timestamp>
            <signal>motor2</signal>
            <value type="Double">-1.0</value>
            <severity>NOTICE</severity>
            <unit>DUMPER</unit>
            <description>MOTOR OFF</description>
        </properties>
    </content>
</entry>
</feed>
but it doesn't help. There is also a second entity that our OData service provides, which is called sensors (can be seen in metadata: https://ecme.empolis.com/oauth/LegoService/LegoService.svc/$metadata). When I define a tab sensors it works without any problem and the individual sensors are shown. So far I couldn't figure out what the difference is. Why does Salesforce treat these two entities differently even though it is the same service and exactly the same codebase. The fields of type 'double' and 'DateTimeOffset' that are present in the events and not in the sesnors are not the reason - I checked.
The good news is that I can execute the SOQL queries for the events as well as for the sensors. But still it would be nice to be able to show the external objects in a native tab.

 

 
Ernesto Hernandez 11Ernesto Hernandez 11
Hi, I'm new to the Salesforce world. I'm studying the Lightning Connect topic and did the exercise/example in this link https://developer.salesforce.com/trailhead/lightning_connect/lightning_connect_introduction. Everything is fine, but when I try to view an Order record, I got this error: 

"The external system responded with an HTTP error "400 Bad Request". The system tried to reach this URL: https://orderdb.herokuapp.com/orders.svc/Orders?$top=2&$filter=orderID+eq+/x&$select=customerID,orderDate,orderID,shippedDate"

So, I would like to know what happened with this point Pat said: "We are passing '%2Fx' as the id. I'm still investigating why this is happening."

If a change the '/x' for a number, let's say '1' the URL works fine and I can see the XML returned by the browser corresponding to the Order details I wanted to see. But inside my dev ORG, I can't do this in order to get it working.

Do you guys already know about this in the Lightning Connect Example in the link provided before?

Thanks in advance!