Cosmos Db Trigger is not being run when inserting new document - java

I am using Azure Cosmos DB. I have created a simple trigger in Azure Portal as follows:
var context = getContext();
var request = context.getRequest();
// item to be created in the current operation
var itemToCreate = request.getBody();
itemToCreate["address"] = "test";
// update the item that will be created
request.setBody(itemToCreate);
Unfortunately this trigger is not being triggered when I insert new documents. I have also tried to set the "Trigger Type" to "Post". Am I missing anything?

Great question! I always thought that triggers would run automatically :).
I believe the triggers are not run automatically whenever a document is inserted. What you would need to do is specify the trigger that you want to run when you're creating the document.
What you need to do is register the trigger by passing the trigger name as the request option when sending create document request.
For example, see the code here: https://learn.microsoft.com/en-us/azure/cosmos-db/how-to-use-stored-procedures-triggers-udfs#pre-triggers (copied below as well). Notice the use of PreTriggerInclude in RequestOptions:
dynamic newItem = new
{
category = "Personal",
name = "Groceries",
description = "Pick up strawberries",
isComplete = false
};
Uri containerUri = UriFactory.CreateDocumentCollectionUri("myDatabase", "myContainer");
RequestOptions requestOptions = new RequestOptions { PreTriggerInclude = new List<string> { "trgPreValidateToDoItemTimestamp" } };
await client.CreateDocumentAsync(containerUri, newItem, requestOptions);

Firing triggers automatically in relational databases makes sense since there is schema in
the database, you kind of know what to handle in a trigger logic.
In NoSQL database, since there is no schema, you may end up with a large script to handle all kind of exceptions.
Large script in triggers means higher bills in Cloud. Making triggers automatic can make many customers bill really high specially in IOT solutions.
You can read about Azure Cosmos DB pre/post triggers in my post.
https://h-savran.blogspot.com/2020/03/create-triggers.html

The only way according to the answers from #Guarav Mantri and #Hasan Savaran is to specify the trigger while creating the item through the API. I have managed to do it in Java Azure SDK like that:
RequestOptions options = new RequestOptions();
options.setPreTriggerInclude(Arrays.asList("pre"));
documentClient.createDocument(
collectionLink(),
documentToAdd,
options,
true);
Although I am not happy with this solution because for instance the trigger will not be triggered when creating the item via Portal.

Related

Azure event Grid trigger function is reading all the existing files in Java

I have Created an azure Evet Grid trigger Java function which reads blob files whenever a new file is uploaded to container.
But the problem is when I deployed the function , its reading all the existing files from container. Ideally it should get triggered only when there is a new or updated files uploaded to container.
Here is the code.
#FunctionName("MyEventGridTrigger")
#StorageAccount("AzureWebJobsStorage")
public void run(#EventGridTrigger(name = "eventGridTrigger") String msg,
#BlobInput(name = "blob", dataType = "binary", path = "{data.url}") byte[] byte,
final ExecutionContext context) {
context.getLogger().info("Event Grid trigger function executed.");
// Logic to read file from byte[]
}
Everything working fine, but its reading the existing files.
Thanks in advance.
I have also implemented same type of event grid through azure portal. I followed three steps.
Create Azure Storage Topic :- That is Event Grid System Topic
Event Subscription and Filter :- in this step, there are two main point
a. Event type :- Tell when event trigger for example create blob (when file is uploaded in blob) or delete blob.
b. End Point Type:- Which subscribe the event like azure function. At this point give information about azure function.
Handle Event with AzureFunction :- Write Code for handle event or action after event fire.
Please click on this link for more help :- Create, view, and manage Event Grid system topics in the Azure portal
By this, you can start your journey in azure and then you can figure it out that how can do by without azure portal. But for custom event grid also you need to create event grid topic.
Note :- Before using Event Grid in azure, Need to register Event Grid Resource Provide first
Please let me know if you still are facing issue.

Multiple Firebase projects in a single android application

I'm trying to build an android application using Firebase that demands two separate databases (teachers and students) in a single application. I searched for the solution all over the internet but all I got is this solution- Multiple Firebase projects in one app, which seems to be a great solution but I didn't understand.
So, how do I merge two firebase projects in a single application?
Yes, you can follow that guide https://firebase.google.com/docs/projects/multiprojects#java.
Basically, you need to initiate the firebase app providing configuration manually
// [START firebase_options]
// Manually configure Firebase Options. The following fields are REQUIRED:
// - Project ID
// - App ID
// - API Key
FirebaseOptions options1 = new FirebaseOptions.Builder()
.setProjectId("my-firebase-project")
.setApplicationId("1:27992087142:android:ce3b6448250083d1")
.setApiKey("AIzaSyADUe90ULnQDuGShD9W23RDP0xmeDc6Mvw")
// setDatabaseURL(...)
// setStorageBucket(...)
.build();
FirebaseOptions options2 = new FirebaseOptions.Builder()
.setProjectId("my-firebase-project")
.setApplicationId("1:27992087142:android:ce3b6448250083d1")
.setApiKey("AIzaSyADUe90ULnQDuGShD9W23RDP0xmeDc6Mvw")
// setDatabaseURL(...)
// setStorageBucket(...)
.build();
// [END firebase_options]
// [START firebase_secondary]
// Initialize with secondary app
FirebaseApp.initializeApp(this /* Context */, options1, "first");
FirebaseApp.initializeApp(this /* Context */, options2, "secondary");
FirebaseApp first = FirebaseApp.getInstance("first");
FirebaseApp secondary = FirebaseApp.getInstance("secondary");
You can get all required data from google-service.json
Later you can get a database from that FirebaseApp, for example
FirebaseDatabase secondaryDatabase = FirebaseDatabase.getInstance(secondary);
Then you just work with the project like before.
The example you mentioned can be used in the following way.
You can create two main tables in firebase db and then you can do operations by
val reference = FirebaseDatabase.getInstance().getReference()
val teacher = reference.child("teacher")//refers to the teacher table
val student = reference.child("student")//refers to the student table
You don't need to implement the communities solution that is described in that link anymore.
According to this:
Sometimes you need to access different projects using the same APIs - for example, accessing multiple database instances. In most cases there is a central Firebase application object that manages the configuration for all the Firebase APIs. This object is initialized as part of your normal setup. However, when you want to access multiple projects from a single application, you’ll need a distinct Firebase application object to reference each one individually. It’s up to you to initialize these other instances.
you need to first create a Firebase options object to hold the configuration data for the Firebase application, like this:
// Manually configure Firebase Options. The following fields are REQUIRED:
// - Project ID
// - App ID
// - API Key
FirebaseOptions options = new FirebaseOptions.Builder()
.setProjectId("my-firebase-project")
.setApplicationId("1:27992087142:android:ce3b6448250083d1")
.setApiKey("AIzaSyADUe90ULnQDuGShD9W23RDP0xmeDc6Mvw")
// setDatabaseURL(...)
// setStorageBucket(...)
.build();
After you have initialized this options object, you can use it to configure an additional Firebase application instance.
For example, if you have another app instance named "otherApp", you can then do this:
// Initialize with secondary app
FirebaseApp.initializeApp(this /* Context */, options, "otherApp");
// Retrieve secondary FirebaseApp
FirebaseApp secondary = FirebaseApp.getInstance("otherApp");
By this way you connect to an alternative Realtime Database.

Multiple Firebase Projects in one app with different persistence setup

I want to setup 2 Firebase in 1 App, but with difference persistence.
One is enable, and the second is disable.
Please inform me how to set it up.
I take code from link below,
Multiple Firebase projects in one app
but it didn't explain,
how to setup persistence for the second Firebase.
I want to enable persistence for 1st Firebase.
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
And disable persistence for 2nd Firebase.
FirebaseDatabase.getInstance().setPersistenceEnabled(false);
As we see, that getInstance is static method,
how do we know that,
the returned FirebaseDatabase instance,
will belong to 1st or 2nd Firebase.
private void initSecondFirebaseAcct()
{
FirebaseOptions options = new FirebaseOptions.Builder()
.setApplicationId("<your application id>")
.setApiKey("<your api key>")
.setDatabaseUrl("<your DB url that ends in 'firebaseio.com/' ")
.build();
try
{
FirebaseApp.initializeApp(this, options, "<database tag>");
}catch (Exception e){
Log.d("Firebase error", "App already exists");
}
mMySecondApp = FirebaseApp.getInstance("<database tag>");
mSecondDBRef = FirebaseDatabase.getInstance(mMySecondApp).getReference();
}
The way to make sure you are referencing the first or second Firebase app is to provide the specific FirebaseApp instance as a parameter to:
FireDatabase.getInstance(<app instance here>).setPersistenceEnabled().
If you use FirebaseDatabase.getInstance() you will receive the default instance, the first database app. So just provide the second instance as a parameter and you'll be good to go.

Parse.com: Get unique number when saving

I use the Parse.com Cloud service in my Android app to sync data between devices.
I use the app mainly offline and use the local data store.
There is one class called Point that has a unique number as identifier I want to display. So when working offline I want to create a Point as draft (with a draft text as number) and when synchronizing I want it to get the real number that is unique over all the devices.
How would I set the number when saving? I was thinking about adding a WebHook in the cloud when saving the Point and giving it a unique number and then in my app use
newPoint.saveEventually(new SaveCallback() {
public void done(ParseException e) {
//query for the number
}
});
to query the point from the cloud to get the number after it has been saved. But this seems kind of too complicated for such a simple requirement. And I am not sure if the SaveCallback() is always triggered when saving it.
I would recommend using an afterSave trigger on the Point class to set the unique identifier when the object is newly created. Then, as you've mentioned, you'll need to fetch the value before displaying it.
Here's what the cloud code could look like:
// Assign the Point a unique identifier on creation
Parse.Cloud.afterSave("Point", function(request) {
// Check if the Point is new
if (!(request.object.existed())) {
// Get the unique identifier
var uniqueIdentifier = ...
// Set the unique identifier
request.object.set('uniqueIdentifier', uniqueIdentifier);
}
});
One important bit of information to keep in mind about using saveEventually with SaveCallback() is:
The callback will only be called if the operation completes within the
current app lifecycle. If the app is closed, the callback can't be
called, even if the save eventually is completed.
Source: Hector Ramos
If the unique identifier should be immediately displayed in the app or if the callback needs to be handled consistently, it would probably be best to use saveInBackground rather than saveEventually.
Another option would be to dynamically change the callback depending on network availability and/or offline settings. For example, if the offline mode is used anytime when the cell signal or wifi is unavailable, then network reachability could be used to check for a network and then use saveInBackground or saveEventually as appropriate.
Update
OP ended up using this code:
Parse.Cloud.beforeSave("Point", function(request, response) {
if (!(request.object.existed())) {
var query = new Parse.Query("Point");
query.addDescending("uniqueIdentifier");
query.first({
success: function(result) {
var maxId = result.get("uniqueIdentifier");
request.object.set("uniqueIdentifier", maxId + 1);
},
error: function() {
}
});
}
response.success();
});

Spring Facebook Template map fetchObject to PagedList

I'm using the following approach to return a Facebook user's music preferences:
//FIXME: Fetch results in a single operation
val likes = facebook.likeOperations().music
val artists = ArrayList<Artist>()
for (musicLiked in likes)
{
val musicProfile = facebook.fetchObject(musicLiked.id, Page::class.java, "id", "name", "genre");
artists.add(Artist(name = musicProfile.name, genre = musicProfile.genre))
}
The above approach won't scale, since we have an additional network operation for each artist the user likes.
I tried:
I tried using facebook.likeOperations.music however this doesn't fetch genre.
Question:
I would like to use facebook.fetchObject with a query that returns a PagedList. How to do this?
(No need to post example code in Kotlin if you prefer or are more familiar with Java - I'll be happy with information in any language).
Facebook api uses "fields" parameter in requests to return custom fields for objects. This parameter can be also used for liked music rest request.
me/music?fields=id,genre,name
above link will return all liked music with id, genre and name of the artist/group. Unfortunately FacebookTemplate does not have method which will apply for your needs. The method Facebook.likeOperations() returns instance of the LikeTemplate class which has constant PAGE_FIELDS with value
private static final String PAGE_FIELDS = "id,name,category,description,location,website,picture,phone,affiliation,company_overview,likes,checkins";
In above constant you do not have genre field. So you have two ways:
You can simply use facebook rest api with some rest library
You can override FacebookTemplate and return your own implementation of LikeTemplate as result of the likeOperations() method. You implementation of the LikeTemplate class should have different value in mentioned constant (added genre field at the end of the string)
Maybe some one will be more helpful but in my knowledge you do not have other options.
Thanks to advice given in #burovmarley's answer, I inspected the source and came up with:
val music = facebook.fetchConnections(userPage.id, "music", Page::class.java,
PagingParameters(25, 0, null, null).toMap(), "id,name,,genre")
for (musicLiked in music)
{
println("likes: ${musicLiked.name}, genre: ${musicLiked.genre}")
}
This allows using Spring Social Facebook as an unmodified dependency, and without issuing a pull request, which seem to be fairly slow in processing through the queue at the present time.

Categories