Persisting a Drools Knowledge Session - jboss

Is it possible to persist a Knowledge Session in Drools? If so, how?
I have facts stored in a database and i'd like to avoid reloading all of them in a new session everytime a new fact is added.
At the moment, when there's a new fact, the fact is stored in the database and then Drools is called: it loads all facts in its session and then fires the rules. The session is lost between calls.

Yes, you can persist sessions to any "binary stream", i.e., files, databases, your in-memory cache, etc. You can also use JPA to manage the persistence for you. Documentation:
http://docs.jboss.org/drools/release/5.4.0.Final/drools-expert-docs/html_single/index.html#d0e3799

Related

How is tracked data in an ORM kept up to date?

How does something such as Entity Framework track changes to it's data when data changes could originate from other sources? For eg: When there is a cluster of the same asp net core app running and if one app updates a record but it's being tracked on a different instance and that instance receives a get request wouldn't it send out of date data?
Basically, how do ORMs preserve ACIDity if they perform local change tracking?
It helps to think of EF contexts and their local caching especially as short-lived. When you read an entity, that entity's "lifespan" should be thought of as matching the lifespan of the DbContext that originated it. Beyond that lifespan, the object is effectively just assumed to be like any other potentially stale copy of the data. Even within that lifespan it does not synchronize with the underlying data source, so the point of truth is when SaveChanges is called. The caching EF provides is more around the scenario of: "I'm going to load some entities, and those entities reference other entities. As the code iterates over the entities, when it comes across a reference to something else, EF will check to see if that something else has already been loaded and serve it before going to the DB." So in that sense, a long-lived DbContext is a bad thing because some of that cached data could be quite old and stale, and as the DbContext loads more data sifting through these tracked entities gets slower and the context consumes more memory.
In web applications, the DbContext is scoped typically to a single request, or shorter than that. (Unit of Work) This means that edits on concurrently handled requests aren't notified of each other's changes, and neither request sees changes made by other sources between the time those request contexts loaded their data and prepared to save. EF can be made aware of what to check for concurrent changes, normally a row version timestamp, and can block an update where this check fails. Beyond that, it is the developer that has to determine what action to take. This often means catching a concurrency fault and then handing off to an appropriate handler to log the details and notify the user. This could be a First-in-wins scenario where the user is notified that their changes failed and to try again; (with the refreshed data provided) A Last-in-wins scenario where the user is prompted that there have been changes but can overwrite; (and hopefully logged the event in case there are disputes/questions) Or a Merge where the system inspects the changes and provides details of any conflicts and changes for the user to review and adjust/accept/or cancel their update.
EF can help detect this, but ultimately the developer has to code for what to do about it.
In terms of detecting concurrent edits as they happen, that requires deliberate coding to do things like communicating changes between sessions (publish/subscribe) where each session listens for updates to entities it's actively working on, and broadcasting changes to entities as it updates them. To detect possible other changes to data by other sources means another process to listen for DB updates (beyond changes it already knows about made by the system) and broadcasting those change notifications to any active sessions. Certainly a very cool thing to see working in action, but the cost & complexity that it introduces has to be justified beyond just handling concurrency issues on save. :)

JPA second level cache update in case of USE store mode

I'm just reading about cache store modes in JPA, and I see the followings:
If data is already in the cache, setting the store mode to USE will not force a refresh when data is read from the database.
It is really strange for me, because I don't understand that why is it great to not to update the cache if the database contains different state of the entity, and I am also curious about in which cases will the cache be updated and in which not.
Thank You in advance.

PersistenceContext propagation

I'm migrating an application from desktop to web. In the desktop application, users connect to an Oracle database using different database users, ie users are managed by Oracle, not within a database table. All use the same scheme to store and manage data, PLMU_PROD.
I have to implement authentication (JPA) for the Web application and, as I read, I have to create a EntityManagerFactory for each database user.
The other option I'm thinking is to create a table of users / passwords and use the same EntityManagerFactory to serve all EntityManager, as all users will access the same data that is in the scheme PLMU_PROD.
I wonder if the PersistenceContext is shared between different EntityManagerFactories, as my web server has little RAM and do not want to waste it having duplicate entities.
Thanks for your time!
What you seem to be referring to is caching. JPA requires that EntityManagers keep entities cached so that they can track changes. So each EntityManager is required to have its own cache, keeping changes made in one separate from changes that might be made concurrently in others - transaction isolation. Within EclipseLink, there is a concept of a second level cache that is shared at the EMFactory level. http://wiki.eclipse.org/EclipseLink/Examples/JPA/Caching is a good document on caching in EclipseLink. This second level cache helps avoid database access and can be disabled as required. If your EntityManagers do not need to track changes, such as if the application is read-only and the entitys are not modified, you can set queries to return entities from the shared cache so that only a single instance of the data exists using the read-only query hint: http://www.eclipse.org/eclipselink/documentation/2.4/jpa/extensions/q_read_only.htm#readonly
Read-only instances can allow avoiding duplication and using resources unnecessarily, but you will need to manage them appropriately and get managed copies from the EntityManager before making changes.

Make sure Entity framework always reads from database?

I have this applikation that is actually two applications, a webapplication and a console application. The console application is used as a scheduled task on the windows machine and is executed 3 times a day to to some recurring work. Both application uses the same Model and repository that is placed in a seperate projekt (class library). The problem is that if the console application need to make som changes to the database it updates the model entity and save the changes to database but when this happens the context in the webbapplication is unaware of this and therefore the object context is not refreshed with the new/updated data and the user of the application can not see the changes.
My question is: Is there a way to tell the objectcontext to always load data from the database, either on the hole objectcontext or for a specific query?
/Regards Vinblad
I don't think you should have this problem in web application. ObjectContext in web application should be created per request so only requests processing during update should be affected.
Anyway there are few methods wich can force ObjectContext to reload data. Queries and load functions allow passing MergeOption which should be able to overwrite current data. But the most interesting should be Refresh method especially with this application.
By Using a DbSet you can you can also make use of the .AsNoTracking() method.
Whenever you run something like
context.Entities.FirstOrDefault()
or whatever query against the context, the data is actually fetched from the database, so you shouldn't be having a problem.
What is your ObjectContext lifetime in the webapp? The ObjectContext is a UnitOfWork, so it should be only created to fetch/write/update data and disposed quickly afterwards.
You can find a similar question here:
Refresh ObjectContext or recreate it to reflect changes made to the database?
FWIW, creating a new (anonymous) object in the query also forces a round trip to the database:
' queries from memory
context.Entities.FirstOrDefault()
' queries from db
context.Entities.Select(Function(x) New With {p.ID, p.Name}).FirstOrDefault()
Please forgive the VB, it's my native language :)

ASP.NET Storing global variables - accessible from every page

I am building a large application and I ususally use a simple session to store private global information however as the application could be rather large I belive this could be a problem due to the amount of memory sessions it could have.
Is there a better way to store such variables?
For example, when the user logs in I want to store data about that user and display it where needed without having to query the database each time.
Sessions are the way to go here, they are intended to persist information about the current session across requests. There is no other object in the ASP.NET framework that has this intention.
You could use the Cache, or store in the Application collection, but then the responsibility of uniquely identifying the individual session data is up to you.
What's also up to you is handling when the session terminates, and freeing up the instances that are stored in those collections (Cache or Application).
It's really a bad idea to start to ask these questions based on what you might "think" will happen. This is a form of premature optimization, and you should avoid it. Rather, use Sessions, as they were intended for this purpose, then measure where your bottlenecks are and address them, should performance be an issue when testing.
use cookies - they would work irrespective of your load balance environments
other options include:
1) writing your sessionvalues to a sql database - you can configure your asp.net app to configure session state to use sql server - but this has its own problems as sessions never time out (so u need to handle this via code explicitly)
2) if not using sql server - basically you would face a problem when you have too many users and you implement load balancing on your web server - so a user can go to a different web server in the same session (and it would not work)
there is a work around for this too - its called STICKY SESSIONS - where your web server guarantees your user would always hit the same web server within the session
3) with .net 2.0 provider model, you can even write your own session storage provider by implementing their delegates - so you can create your own xml files on your web server / shared server to read / write session data there :-)
so there are many ways you can solve this. however the simplest and cost effective solution is to use cookies
You might use Cache. That has built-in mechanism to free up when memory is running out...
Definitely use cookies for this. The best approach is to make yourself a cookies wrapper class that will do all the heavy lifting for you - checking if cookie is null, accessing the httpcontext, etc. No need to mess up your code with all that; just abstract it all out into cookies.cs or .vb.
SetCookieValue(someValue, cookieName); //there will be some expiration concerns here as well
myValue = GetCookieValue(cookieName);
Christian Weiss has a good strategy.
If you think your data is too large for the Session, I would consider a database of some sort using cache so that you don't unnecessary calls.
If it is per-user-session data you're storing, using the ASP.NET Session is definitely your best bet. If you're most worried about memory usage then you can use MSSQL mode. The data has to live somewhere and the choice of which session mode to use is dependent on your environment and the usage patterns of your users.
Don't assume there will be a problem with the size of session state until you see such a problem and have tried to solve it. For instance, it's possible that, although the application as a whole may use a large amount of session state, that any given user may not use that much in the course of a session.
I's also possible that changing from the default session state provider to the SQL provider or state server provider would ease a memory issue.
You can use Cache, but Cache is application-wide. You would need to qualify Cache entries with the user id or session id: Cache[userID + ".MyCacheEntry"].
Do not, under any circumstances, use static variables to store this data. As suggested by your subject line, they are application-wide, not per-user.