Azure Document DB - Java 1.9.5 | Authorization Error - java

I have a collection with some documents in it. And in my application I am creating this collection first and then inserting documents. Also, based on the requirement I need to truncate (delete all documents) the collection as well. Using document db java api I have written the following code for my this purpose-
DocumentClient documentClient = getConnection(masterkey, server, portNo);
List<Database> databaseList = documentClient.queryDatabases("SELECT * FROM root r WHERE r.id='" + schemaName + "'", null).getQueryIterable().toList();
DocumentCollection collection = null;
Database databaseCache = (Database)databaseList.get(0);
List<DocumentCollection> collectionList = documentClient.queryCollections(databaseCache.getSelfLink(), "SELECT * FROM root r WHERE r.id='" + collectionName + "'", null).getQueryIterable().toList();
// truncate logic
if (collectionList.size() > 0) {
collection = ((DocumentCollection) collectionList.get(0));
if (truncate) {
try {
documentClient.deleteDocument(collection.getSelfLink(), null);
} catch (DocumentClientException e) {
e.printStackTrace();
}
}
} else { // create logic
RequestOptions requestOptions = new RequestOptions();
requestOptions.setOfferType("S1");
collection = new DocumentCollection();
collection.setId(collectionName);
try {
collection = documentClient.createCollection(databaseCache.getSelfLink(), collection, requestOptions).getResource();
} catch (DocumentClientException e) {
e.printStackTrace();
}
With the above code I am able to create a new collection successfully. Also, I am able to insert documents as well in this collection. But while truncating the collection I am getting below error-
com.microsoft.azure.documentdb.DocumentClientException: The input authorization token can't serve the request. Please check that the expected payload is built as per the protocol, and check the key being used. Server used the following payload to sign: 'delete
colls
eyckqjnw0ae=
I am using Azure Document DB Java API version 1.9.5.
It will be of great help if you can point out the error in my code or if there is any other better way of truncating collection. I would really appreciate any kind of help here.

According to your description & code, I think the issue was caused by the code below.
try {
documentClient.deleteDocument(collection.getSelfLink(), null);
} catch (DocumentClientException e) {
e.printStackTrace();
}
It seems that you want to delete a document via the code above, but pass the argument documentLink with a collection link.
So if your real intention is to delete a collection, please using the method DocumentClient.deleteCollection(collectionLink, options).

Related

creating a mongodb healthcheck (in dropwizard)

Not necessarily specific to dropwizard, but for the life of me I can't figure out how to easily create a healthcheck for mongodb. This is in java, using version 3.3.0 of mongodb's own java driver.
I was hoping there would be a method that doesn't change the state of the database if it succeeds, but also throws an Exception when the query (or connection, or whatever) fails in order to return a health or unhealthy state. Ideally I'd perform a find, but this doesn't throw an Exception as far as I can tell.
I would just list all collections in database like:
MongoClient client = new MongoClient(addr, opts);
MongoDatabase db = client.getDatabase(database);
try {
MongoIterable<String> allCollections = db.listCollectionNames();
for (String collection : allCollections) {
System.out.println("MongoDB collection: " + collection);
}
} catch (Exception me) {
// problems with mongodb
}

Invalid statement. Please check aliases, field identifiers, projections and query conditions

I'm using Dynamicloud and something is wrong in my code.
This is my code:
DynamicProvider<ContactForm> provider = new DynamicProviderImpl<ContactForm>(new RecordCredential(csk, aci));
contactFormModel.setBoundClass(ContactForm.class);
Query<ContactForm> query = provider.createQuery(contactFormModel);
try {
RecordResults<ContactForm> list = query.add(Conditions.like("contact.namef", "ProBusiness%")).list();
System.out.println("list = " + list.getFastReturnedSize());
if (list.getFastReturnedSize() > 0) {
System.out.println("Contact Name = " + list.getRecords().get(0).getName());
System.out.println("Contact Comments = " + list.getRecords().get(0).getComments());
}
} catch (DynamicloudProviderException e) {
e.printStackTrace();
}
This code throws the following Exception:
org.dynamicloud.exception.DynamicloudProviderException: Invalid statement. Please check aliases, field identifiers, projections and query conditions.
What's wrong?
Thanks!
Hi
The problems is the contact word right before namef in your like condition.
Dynamicloud API provides a method to set the alias of a model. For example, the aliases are used in situations where you need to execute JOINS
The problem is solved by calling the method setAlias from the query object query.setAlias("contact")
query.setAlias("contact");
Dynamicloud resources about Query class
Hope this helps

createUserDefinedFunction : if already exists?

I'm using azure-documentdb java SDK in order to create and use "User Defined Functions (UDFs)"
So from the official documentation I finally find the way (with a Java client) on how to create an UDF:
String regexUdfJson = "{"
+ "id:\"REGEX_MATCH\","
+ "body:\"function (input, pattern) { return input.match(pattern) !== null; }\","
+ "}";
UserDefinedFunction udfREGEX = new UserDefinedFunction(regexUdfJson);
getDC().createUserDefinedFunction(
myCollection.getSelfLink(),
udfREGEX,
new RequestOptions());
And here is a sample query :
SELECT * FROM root r WHERE udf.REGEX_MATCH(r.name, "mytest_.*")
I had to create the UDF one time only because I got an exception if I try to recreate an existing UDF:
DocumentClientException: Message: {"Errors":["The input name presented is already taken. Ensure to provide a unique name property for this resource type."]}
How should I do to know if the UDF already exists ?
I try to use "readUserDefinedFunctions" function without success. Any example / other ideas ?
Maybe for the long term, should we suggest a "createOrReplaceUserDefinedFunction(...)" on azure feedback
You can check for existing UDFs by running query using queryUserDefinedFunctions.
Example:
List<UserDefinedFunction> udfs = client.queryUserDefinedFunctions(
myCollection.getSelfLink(),
new SqlQuerySpec("SELECT * FROM root r WHERE r.id=#id",
new SqlParameterCollection(new SqlParameter("#id", myUdfId))),
null).getQueryIterable().toList();
if (udfs.size() > 0) {
// Found UDF.
}
An answer for .NET users.
`var collectionAltLink = documentCollections["myCollection"].AltLink; // Target collection's AltLink
var udfLink = $"{collectionAltLink}/udfs/{sampleUdfId}"; // sampleUdfId is your UDF Id
var result = await _client.ReadUserDefinedFunctionAsync(udfLink);
var resource = result.Resource;
if (resource != null)
{
// The UDF with udfId exists
}`
Here _client is Azure's DocumentClient and documentCollections is a dictionary of your documentDb collections.
If there's no such UDF in the mentioned collection, the _client throws a NotFound exception.

Filtering fields in RFC_READ_TABLE with SAP JCo

I am attempting to write a simple java utility that extracts data from SAP into a MySQL database, using JCo. I have understood the JCo documentation and tried out the relevant examples mentioned in SAP help portal, I am able to retrieve data from Table and insert into MySQL DB.
What I would like to have is a facility to filter data in following two ways :
I would like to fetch only the required fields.
I would like to fetch rows only if the value of the a particular field matches certain pattern.
After doing some research I didn't find any way to specify query parameters so that it retrieves only the filtered data, it basically queries all the fields from a Table, I think I will have to filter out the data that I don't want in my java-client layer. Please let me know if I am missing out something here.
Here is a code example :
public static void readTables() throws JCoException, IOException {
final JCoDestination destination = JCoDestinationManager
.getDestination(DESTINATION_NAME2);
final JCoFunction function = destination.getRepository().getFunction(
"RFC_READ_TABLE");
function.getImportParameterList().setValue("QUERY_TABLE", "DD02L");
function.getImportParameterList().setValue("DELIMITER", ",");
if (function == null) {
throw new RuntimeException("BAPI RFC_READ_TABLE not found in SAP.");
}
try {
function.execute(destination);
} catch (final AbapException e) {
System.out.println(e.toString());
return;
}
final JCoTable codes = function.getTableParameterList().getTable(
"FIELDS");
String header = "SN";
for (int i = 0; i < codes.getNumRows(); i++) {
codes.setRow(i);
header += "," + codes.getString("FIELDNAME");
}
final FileWriter outFile = new FileWriter("out.csv");
outFile.write(header + "\n");
final JCoTable rows = function.getTableParameterList().getTable("DATA");
for (int i = 0; i < rows.getNumRows(); i++) {
rows.setRow(i);
outFile.write(i + "," + rows.getString("WA") + "\n");
outFile.flush();
}
outFile.close();
}
This method tries to read a table where SAP stores meta data or data dictionary and writes the output to a csv file. This works fine but takes 30-40 secs and returns around 4 hundred thousand records with 32 columns. My intention was to ask if there is a way I can restrict my query to return only a particular field, instead of reading all the fields and discarding them in the client layer.
Thanks.
This works fine :
JCoTable table = function.getTableParameterList().getTable("FIELDS");
table.appendRow();
table.setValue("FIELDNAME", "TABNAME");
table.appendRow();
table.setValue("FIELDNAME", "TABCLASS");
Please check this Thread
Thanks.

How can I send from the server-side (Google App Engine, Cloud Endpoints) the information to my client?

I have an Android Application that is stored in the Cloud, with Google App Engine. I use Cloud Endpoints. My problem is that I cannot send the data from the server to my client(Android Device), or better said, so far, I have no idea how to do that.
So far, I have managed to insert data in the datastore, by creating an endpoint and calling the method that is in charge with adding a record in the database(that's located on the server side, in myProject - AppEngine) , using the following code (on the client):\
Noteendpoint.Builder endpointBuilder = new Noteendpoint.Builder(
AndroidHttp.newCompatibleTransport(),
new JacksonFactory(),
new HttpRequestInitializer() {
public void initialize(HttpRequest httpRequest) { }
});
Noteendpoint endpoint = CloudEndpointUtils.updateBuilder(
endpointBuilder).build();
try {
// Construct the note.
Note note = new Note().setDescription("Note DescriptionRoxana");
String noteID = new Date().toString();
note.setId(noteID);
note.setEmailAddress("E-Mail AddressRoxana");
// Insert the Note, by calling a method that's on the server side - insertNote();
Note result = endpoint.insertNote(note).execute();
} catch (IOException e) {
e.printStackTrace();
}
But I cannot see a way of retrieving data from the datastore and to display it on the server side. I tried to do the same, create an endpoint, that will call the method that retrieves all the records in the database (method that is located on the server), but my application crashes.
The code for the method that retrieves data from the datastore is the following:
public CollectionResponse<Note> listNote(
#Nullable #Named("cursor") String cursorString,
#Nullable #Named("limit") Integer limit) {
EntityManager mgr = null;
Cursor cursor = null;
List<Note> execute = null;
try {
mgr = getEntityManager();
Query query = mgr.createQuery("select from Note as Note");
if (cursorString != null && cursorString != "") {
cursor = Cursor.fromWebSafeString(cursorString);
query.setHint(JPACursorHelper.CURSOR_HINT, cursor);
}
if (limit != null) {
query.setFirstResult(0);
query.setMaxResults(limit);
}
execute = (List<Note>) query.getResultList();
cursor = JPACursorHelper.getCursor(execute);
if (cursor != null)
cursorString = cursor.toWebSafeString();
// Tight loop for fetching all entities from datastore and accomodate
// for lazy fetch.
for (Note obj : execute)
;
} finally {
mgr.close();
}
return CollectionResponse.<Note> builder().setItems(execute)
.setNextPageToken(cursorString).build();
}
You see, the returned type is collection response. You have access to this type of data, after performing the following import:
import com.google.api.server.spi.response.CollectionResponse;
I inferred that this is a data type characteristic to the server side, thus, I have no idea how I can cast it into a List, ArrayList, or any other type of collection, that can be used on the client side.
How should I do it then? Since adding data was so easy and so straight forward, I have assumed that retrieving data would be performed in the same manner, but apparently I am missing something essential for this matter.
Thank you in advance!
The classes you use in the backend are not the same as the classes you'll use in the client. Endpoints will generate a set of libraries for you, either on the command line or with tooling like Google Plugin for Eclipse. See Using Endpoints in an Android Client.
The generated class representing the collection of Notes in your example will be named something like NotesCollection. This object will have a method getItems, which provides you a List<Note> you can iterate on in your Android application.
Similar to having an endpoint for inserting data into a datastore model(methods of type POST), you need to have an endpoint for querying the data from the datastore model (methods of type GET). After you define both these methods, you need generate your discovery document and client library so that clients know about both these methods and can call them. If your speaking about displaying the data in the web itself then you can build a Javascript client by using the required client library.

Categories

Resources