I am creating KieBase dynamically and creating a local cache to cache. For each request i am looking into the cache to check the availability in order to not build the base again and improve performance. The KieBase can keep getting updated as the version of the rules gets updated. This will be handled as part of the cache stratergy.
I would like to know if there is a mechanism to load these Kiebase into a KieContainer for each request as i would like to dispose the Container once the request is complete.
Related
If I annotate a bean as #RefreshScope, I can get a new instance of it after its configuration changes (eg. by triggering the refresh by calling /refresh).
But this is exactly I'd like for each of my beans: why would I change a configuration file and then expect the configuration to take effect for some part of the application immediately and for some part only after restart?
So the question is whether it's possible to apply it as a default scope?
Also in a typical Spring Boot application a lot gets auto-configured (eg. datasource), and without a default scope, I'd have to build the beans myself and annotate them properly. (edit: #ConfigurationProperties are automatically refreshed, and since a Spring Boot Datasource auto configuration is based on that, it is refreshed indeed without #RefreshScope)
What am I missing here?
https://cloud.spring.io/spring-cloud-static/spring-cloud.html#_environment_changes and https://cloud.spring.io/spring-cloud-static/spring-cloud.html#_refresh_scope has all the answers.
#ConfigurationProperties are automatically refreshed when /refresh is called, so beans using these properties get the fresh values, for the others and #Value there's #RefreshScope.
I don't think making #RefreshScope default is possible.
The beans annotated with #RefreshScope don't get automatically refreshed after a configuration is changed. It gets refreshed only after the cache entry is invalidated.
From the docs:
Refresh scope beans are lazy proxies that initialize when they are used (i.e., when a method is called), and the scope acts as a cache of initialized values. To force a bean to re-initialize on the next method call, you just need to invalidate its cache entry.
One way to invalidate the cache is by using the /refresh endpoint.
It's valid to note that a refresh-scoped bean can lead to unexpected behavior, please refer to the docs mentioned above to understand why this is not the default behavior.
When application creates multiple state-full kie session, do they share same working memory or they have separate working memory. So if a fact is inserted in one session , will it be available in another session.
A KieSession IS the working memory. You can create multiple, independent KieSessions from a single KieBase, but if you want to broadcast facts to multiple session you will need to implement that mechanism yourself.
Hope it helps,
When you override onStart in Global, would it block the thread running the bootstrap process?
In other words I want to make sure that Play does not start until call returns from onStart.
If this is not the case, what are good solution to do critical init process which need to happen before Play start accepting requests?
Yes, Global.onStart will block before the first request.
The GlobalSettings object in Play is a plugin. When the application is started, the routes are loaded first, then the plugins are loaded serially by calling the onStart method of each. The GlobalSettings plugin comes last in this initialization, which ensures that all other plugins are loaded first so that all of your db connections, cache, etc are available there.
The plugin initialization has to block a single thread to guarantee that:
All plugins are initialized in the exact order that is desired to prevent initialization order errors (if one plugin depends on another initializing first--for example the database plugin must always initialize before the evolutions plugin).
All plugins are initialized before the application can start processing requests. (Otherwise, you wouldn't be able to guarantee the the DB plugin was ready on the first request, for example).
Assume I created a StatefulKnowledgeSession from a given knowledgebase.
The JBPM process in this session can last for multiple days so we need to persist the session between invocations.
Now the knowledge resouces (JBPM Process definitions (BPMN files)) may change while a given process instance is running.
Upon server restart, I will need to reconstruct the correct knowledgebase in order to load the session.
But how do I know which resources to use to rebuild the knowledgebase?
Does a session keep track of the resources which were used to start it?
Do I need to build and manage knowledgebaseconfigurations?
Any help would be greatly appreciated!
Michiel
Typically your application would recreate the kbase the same way it was created the first time. So depending on how you create your kbase, this will involve simply loading the necessary processes again from classpath, from filesystem or from guvnor repository for example.
The session itself doesn't keep track of the kbase (so it can recreate it).
Kris
Hey, I'm working on the model layer for our app here.
Some of the requirements are like this:
It should work on iPhone OS 3.0+.
The source of our data is a RESTful Rails application.
We should cache the data locally using Core Data.
The client code (our UI controllers) should have as little knowledge about any network stuff as possible and should query/update the model with the Core Data API.
I've checked out the WWDC10 Session 117 on Building a Server-driven User Experience, spent some time checking out the Objective Resource, Core Resource, and RestfulCoreData frameworks.
The Objective Resource framework doesn't talk to Core Data on its own and is merely a REST client implementation. The Core Resource and RestfulCoreData all assume you talk to Core Data in your code and they solve all the nuts and bolts in the background on the model layer.
All looks okay so far and initially I though either Core Resource or RestfulCoreData will cover all of the above requirements, but... There's a couple of things none of them seemingly happen to solve correctly:
The main thread should not be blocked while saving local updates to the server.
If the saving operation fails the error should be propagated to the UI and no changes should be saved to the local Core Data storage.
Core Resource happens to issue all of its requests to the server when you call - (BOOL)save:(NSError **)error on your Managed Object Context and therefore is able to provide a correct NSError instance of the underlying requests to the server fail somehow. But it blocks the calling thread until the save operation finishes. FAIL.
RestfulCoreData keeps your -save: calls intact and doesn't introduce any additional waiting time for the client thread. It merely watches out for the NSManagedObjectContextDidSaveNotification and then issues the corresponding requests to the server in the notification handler. But this way the -save: call always completes successfully (well, given Core Data is okay with the saved changes) and the client code that actually called it has no way to know the save might have failed to propagate to the server because of some 404 or 421 or whatever server-side error occurred. And even more, the local storage becomes to have the data updated, but the server never knows about the changes. FAIL.
So, I'm looking for a possible solution / common practices in dealing with all these problems:
I don't want the calling thread to block on each -save: call while the network requests happen.
I want to somehow get notifications in the UI that some sync operation went wrong.
I want the actual Core Data save fail as well if the server requests fail.
Any ideas?
You should really take a look at RestKit (http://restkit.org) for this use case. It is designed to solve the problems of modeling and syncing remote JSON resources to a local Core Data backed cache. It supports an offline mode for working entirely from the cache when there is no network available. All syncing occurs on a background thread (network access, payload parsing, and managed object context merging) and there is a rich set of delegate methods so you can tell what is going on.
There are three basic components:
The UI Action and persisting the change to CoreData
Persisting that change up to the server
Refreshing the UI with the response of the server
An NSOperation + NSOperationQueue will help keep the network requests orderly. A delegate protocol will help your UI classes understand what state the network requests are in, something like:
#protocol NetworkOperationDelegate
- (void)operation:(NSOperation *)op willSendRequest:(NSURLRequest *)request forChangedEntityWithId:(NSManagedObjectID *)entity;
- (void)operation:(NSOperation *)op didSuccessfullySendRequest:(NSURLRequest *)request forChangedEntityWithId:(NSManagedObjectID *)entity;
- (void)operation:(NSOperation *)op encounteredAnError:(NSError *)error afterSendingRequest:(NSURLRequest *)request forChangedEntityWithId:(NSManagedObjectID *)entity;
#end
The protocol format will of course depend on your specific use case but essentially what you're creating is a mechanism by which changes can be "pushed" up to your server.
Next there's the UI loop to consider, to keep your code clean it would be nice to call save: and have the changes automatically pushed up to the server. You can use NSManagedObjectContextDidSave notifications for this.
- (void)managedObjectContextDidSave:(NSNotification *)saveNotification {
NSArray *inserted = [[saveNotification userInfo] valueForKey:NSInsertedObjects];
for (NSManagedObject *obj in inserted) {
//create a new NSOperation for this entity which will invoke the appropraite rest api
//add to operation queue
}
//do the same thing for deleted and updated objects
}
The computational overhead for inserting the network operations should be rather low, however if it creates a noticeable lag on the UI you could simply grab the entity ids out of the save notification and create the operations on a background thread.
If your REST API supports batching, you could even send the entire array across at once and then notify you UI that multiple entities were synchronized.
The only issue I foresee, and for which there is no "real" solution is that the user will not want to wait for their changes to be pushed to the server to be allowed to make more changes. The only good paradigm I have come across is that you allow the user to keep editing objects, and batch their edits together when appropriate, i.e. you do not push on every save notification.
This becomes a sync problem and not one easy to solve. Here's what I'd do: In your iPhone UI use one context and then using another context (and another thread) download the data from your web service. Once it's all there go through the sync/importing processes recommended below and then refresh your UI after everything has imported properly. If things go bad while accessing the network, just roll back the changes in the non UI context. It's a bunch of work, but I think it's the best way to approach it.
Core Data: Efficiently Importing Data
Core Data: Change Management
Core Data: Multi-Threading with Core Data
You need a callback function that's going to run on the other thread (the one where actual server interaction happens) and then put the result code/error info a semi-global data which will be periodically checked by UI thread. Make sure that the wirting of the number that serves as the flag is atomic or you are going to have a race condition - say if your error response is 32 bytes you need an int (whihc should have atomic acces) and then you keep that int in the off/false/not-ready state till your larger data block has been written and only then write "true" to flip the switch so to speak.
For the correlated saving on the client side you have to either just keep that data and not save it till you get OK from the server of make sure that you have a kinnf of rollback option - say a way to delete is server failed.
Beware that it's never going to be 100% safe unless you do full 2-phase commit procedure (client save or delete can fail after the signal from the server server) but that's going to cost you 2 trips to the server at the very least (might cost you 4 if your sole rollback option is delete).
Ideally, you'd do the whole blocking version of the operation on a separate thread but you'd need 4.0 for that.