Getting "oModel.read is not a function" error - odata

While performing Read operation on V4 ODatamodel I'm getting an error saying
oModel.read is not a function
Code
Error
Please let me know how to correct if I did something wrong.

This error is expected.
read method does not exist in oData Model V4.
See below:
read is not a function in V4
However, you can do the same thing with oData V2(recommended approach for working with oData as V4 has still some features missing)
Restrictions with oData V4
oData V2 vs oData V4
Nevertheless, if you need to bind the response items later with a table, you can
do it as:
var oModel = new sap.ui.model.odata.v4.ODataModel({
groupId: "$auto",
serviceUrl: "url",
synchronizationMode: "None",
operationMode: "Server"
}),
oSettings = new sap.ui.model.json.JSONModel({
bOnlyLarge: false,
bFilterGermany: false
});
var oTable = new sap.ui.table.Table({
columns: [{
label: "ProductName",
template: new sap.m.Text({
text: "{Country}"
}),
sortProperty: "ProductName"
}]
});
oTable.setModel(oModel);
oTable.bindRows({
path: "/Products"
});

var oModel = new sap.ui.model.odata.v4.ODataModel({
/* send requests directly. Use $auto for batch request wich will be send automatically on before rendering */
groupId : "$direct",
/* I'll just quote the API documentary:
Controls synchronization between different bindings which refer to the same data for the case data changes in one binding.
Must be set to 'None' which means bindings are not synchronized at all; all other values are not supported and lead to an error.
*/
synchronizationMode : "None",
/*
Root URL of the service to request data from.
*/
serviceUrl : "http://services.odata.org/TripPinRESTierService/",
/*
optional. Group ID that is used for update requests. If no update group ID is specified, mParameters.groupId is used.:
updateGroupId : "$direct"
*/
});

Related

F# with Http.fs - not able to execute GraphQL APIs

I don't see any good documentation about how to execute GraphQL APIs using F# with Http.fs
Kindly share if you have the correct syntax available or point to the correct documentation for the same. I was trying with the Star Wars API given here: https://www.rithmschool.com/blog/an-introduction-to-graphql-queries
URL: https://swapi.graph.cool
Header: 'Content-Type': 'application/json'
JSON Body:
query {
Film (title:"A New Hope" ) {
director
characters {
name
}
}
}
Expected Response same as: https://swapi.graph.cool/
I'm not familiar with Http.fs, but here is a small working example of calling the API using the F# Data Http utility:
Http.RequestString
( "https://swapi.graph.cool",
httpMethod="POST", headers=[ HttpRequestHeaders.ContentType("application/json") ],
body=TextRequest("{\"query\": \"{ allFilms { title } }\"}") )
The main thing is that the body needs to be a JSON value where the actual query is a string stored in a record with a field named "query", i.e. {"query": "...."}.

Create entry in SAPUI5 odata model offline

I'm currently building a sapui5 app with odata. This app has to work offline, however everytime I try to set up a new entity with createEntry, the entry is not created until I run odataModel.submitchanges which performs a PUT request.
How are entries supposed to be correctly created in a offline scenario?
I'm not sure but you should be able to write a json model and use it as odata request. Like this
var mydata = {
"milk": [{
"Store Name": "XXXXXXXXXX",
"Revenue": 321421,
"Cost": 200,
"Consumption": 2321.4
},
{
"Store Name": "AAAAAAAa",
"Revenue": 4550208.3173505,
"Cost": 100,
"Consumption": 493776.33
}]
}
var oModel = new JSONModel();
oModel.setData(myData);
after that you should be able to use this model.

Eve - Is it possible to unset a key from a document?

In a schema with optional values such as code in the example:
'code': {
'type': 'string',
},
'name': {
'type': 'string',
'required': True,
},
'email': {
'type': 'string',
'required': True
}
Let's say there's an inserted document with a value for code. Can I unset the code key like mongodb $unset does, using Eve somehow?
One way to achieve this is to setup a default projection for the endpoint.
Limiting the Fieldset Exposed by the API Endpoint
By default API responses to GET requests will include all fields defined by the corresponding resource schema. The projection setting of the datasource resource keyword allows you to redefine the fields.
people = {
'datasource': {
'projection': {'username': 1}
}
}
The above setting will expose only the username field to GET requests, no matter the schema defined for the resource.
Another option is to leverage MongoDB Aggregation Framework itself. Just set the endpoint so that a aggregation is performed before data is returned to the client. The following should work (see the docs for details):
posts = {
'datasource': {
'aggregation': {
'pipeline': [{"$unset": "code"}]
}
}
}
You need Eve v0.7 for aggregation support.
I doubt you can do it with a PATCH request, but a PUT request should do.
import requests
# get original doc
resp = requests.get(document_url)
# prepare a new document
doc = resp.json()
new_doc = {k: v for k, v in doc.items() if not k.startswith('_')}
del new_doc['code']
# overwrite the complete document
resp = requests.put(document_url, json=new_doc, headers={'If-Match': doc['_etag']}

SapUI5 and Odata Service issue

I am trying to consume Gateway OData Services in sapui5 app.
Metadata - /sap/opu/odata/SAP/ZUSER_MANAGE_SRV/$metadata as follows:
UserdataSet - /sap/opu/odata/SAP/ZUSER_MANAGE_SRV/UserdataSet as follows:
MY CODE
var oModel = new sap.ui.model.odata.ODataModel("http://Host:Port/sap/opu/odata/SAP/ZUSER_MANAGE_SRV", false,"USER","Password");
var app = new sap.m.App("myApp",{});
var oTable = new sap.m.Table("list1", {
growing: true,
growingThreshold: 200,
//mode: sap.m.ListMode.SingleSelect,
columns: [
new sap.m.Column({
header: new sap.m.Label({text: "ID"})
}),
new sap.m.Column({
header: new sap.m.Label({text: "First Name"})
}),
new sap.m.Column({
header: new sap.m.Label({text: "Last Name"})
})
],
items: {
path: "/UserdataSet",
template: new sap.m.ColumnListItem({
cells: [
new sap.m.Input({value: "{EUname}"}),
new sap.m.Input({value: "{EFirstname}"}),
new sap.m.Input({value: "{ELastname}"})
]
})
}
});
oTable.setModel(oModel);
var page1 = new sap.m.Page("page1",{
title: "App",
content: [oTable]
});
app.addPage(page1);
return app;
Getting error as - uncaught exception: [object Object].
Detailed Error:
Please help, whats wrong with my code?
Your OData service needs to be on the same server or needs to appear to be coming from the same server as your UI5 application. If it's not on the same server you should get Gateway to produce CORS headers.
Please find more info on CORS and how to get Gateway to produce these headers here: http://scn.sap.com/community/gateway/blog/2014/09/23/solve-cors-with-gateway-and-chrome
The Error is not very clear maybe chrome will show an more detailed error in this case.
If your application server and odata service are not from the same origin, the SOP (same origin policy) restricts this action.
Two pages have the same origin if the protocol, port and host are the same for both pages.
see https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy for more details.
you can start chrome with --disable-web-security flag:
In CMD:
C:/<path to chrome app>/chrome.exe --disable-web-security
!!! ONLY FOR DEVELOPMENT REASONS !!!

Syntax for submitting a mutation to a graphql-relay mutationWithClientMutationId

I defined a GraphQL Mutation using graphql-relay but am having issues figuring out how to submit a mutation to it.
Here is the relevant schema:
const userType = new GraphQLObjectType({
name: 'User',
description: 'user',
fields: () => ({
id: {
type: new GraphQLNonNull(GraphQLString),
description: 'The UUID for the user.',
resolve(user) {
return user.uuid;
},
},
})
});
const registerUser = mutationWithClientMutationId({
name: 'registerUser',
inputFields: {
},
outputFields: {
user: {
type: userType,
resolve: (payload) => {
models.user.findById(payload.userId);
}
},
},
mutateAndGetPayload: (args) => {
var newUser = models.user.build().save();
return {
userId: newUser.id,
};
}
});
const rootMutation = new GraphQLObjectType({
name: 'RootMutationType',
fields: {
registerUser: registerUser,
},
});
const schema = new GraphQLSchema({
query: rootQuery,
mutation: rootMutation,
});
What should an HTTP call look like to register a new user and get back the userId?
Thanks!
I want to point out that I see that you're saying that your mutation requires no parameters - how does it know what the new user's details are? You'll probably need some parameters on that mutation, eventually. They would be available to your mutateAndGetPayload on that first function parameter. (I'm not saying every mutation needs parameters, but this one probably does)
If you're using Relay, there is some pretty good information on the official document as to how to use your mutations from Relay. Particularly down at the bottom where it shows the various mutator configs. If you're using connections, you may want to use RANGE_ADD to add this new account to the Relay store manually, otherwise if you'd like to perform a more broad refetch you can use FIELDS_CHANGE. You said you need the new user id after the mutation finishes. If you're using Relay, you may need to look into REQUIRED_CHILDREN to specify that regardless of the computed query that Relay will build, you always want that id to be queried.
The output of your mutation is a userType, so you'd be able to access it with a fragment on the payload type, which would probably be RegisterUserPayload, that might look something like ...
fragment on RegisterUserPayload {
user {
id
}
}
Now, that's assuming you're using Relay. If you'd like to try this out manually via GraphiQL, then you can use the examples of how to do mutations through there on the GraphQL Mutation docs. There's a direct example of how you'd query your mutation.
Last, since you asked how to do this at a low level of issuing the HTTP request yourself, for that you can look at express-graphql documentation, which explains how to query it.
I figured out a mutation format that worked:
mutation RootMutationType {
registerUser(input:{clientMutationId:"123"}){
clientMutationId, user { id }
}
}

Resources