Multi session / multi-tenant web app with SWI-Prolog

I’ll see whether I can find some time. In the mean while though, it isn’t really clear what you want to preserve for which reason during a session. The more complicated Pengine or engine approach allow you to use the Prolog flow of control as part of the state. The normal session data merely provides a Prolog dynamic database that is associated to the session.

In order to be quick and secure on web service execution, I would like to know that my application server (e.g.) be hosting a prolog interpreter with loaded kb’s for each web user individually (what would be the cost here). So that there is no need to re-load any kb from scratch when that particular user executes some goals. In general this is how tomcat would handle that.

  1. new user on JSP servlet (e.g. JSP but this can be any tech) request -> generate sessionid and allocate application (e.g. prolog listening) in memory
  2. on user actions (goals), execute goals (without reloading any kb each time) and respond to user.
  3. on user logout, release application, invalidate session.

There should be no need to interactively backtrack and do what a prolog user does/did since years inside a prolog console. This would be a use of prolog as dedidated interpreter executing a task, accepting some interactions via input/ouput not necessarily backtracking - with a user env - each user another env. Is this today possible? There is a need to encapsulate execution and env to isolate every (web) user from the other and to avoid reloading of kbs on goals (*), to preserve a state and an interaction via input/output.

(*) of course not talking of lazy evaluation, which is a sane principle to load if needed, to compute if needed.

I’m not entirely sure this is what you are after, but please have a look at

This uses the engine approach to create a private space. It also uses a private module. This isn’t really needed: you can also define the predicates that represent the user’s knowledge bases a :- thread_local p/1, q/2, ..... In most cases the latter approach is probably easier. Only of the different users have knowledge bases that are completely differenty structured (using different predicates that are not known a priory), the temporary module approach becomes necessary (that is why it is used for Pengines, where every user writes his/her own program (=knowledge base).

Does this start to make sense?

This is de-facto interesting in general and represents one of the major steps of a prolog env to get industrial. Thank you very much for your link and example code. On my website services start by a JSP page (I can change that). After that, a session is already computed by Java.

What I cannot (yet) figure out is the multi-tenancy on the prolog spaces. The following is how I still understand it from your code and proposal (thank you): I start on a linux server an swi-prolog process inside a terminal and load what you show in the link. Then the next user calls the same web address served by that special prolog web service predicates (as per your link). So in this way we keep ONE prolog space (engine?) for several users.

How can the multi-tenancy here be preserved (a tenant being a company, inside which several users might work and (if we want…) share some prolog space inside a tenant.) ?

A possible generalized scenario could be:

User 1 calls the served address at time t1 and executes some goals (which might affect his kb)

User 2 calls the served address at time t2 and executes some goals (which might affect his kb)




User m calls the served address at time tn and executes some goals (which might affect his kb)

I need to preserve for each user a completely secured prolog space, forbidding any side effects e.g. User1 might perform (assert/retract/load/drop) on the kb, so that User 3 suddenly gets another knowledge base … ?

Is this something your nice prolog server predicates could handle?

Thank you

Yes in the sense that isolation is preserved if the code executed by the server is not malicious. This implies that the code must keep its state in thread_local predicates or in the private module and should not modify anything else. If tenants can upload code and cannot be trusted this breaks down.

The Pengine approach can deal with malicious code, but now the code must be injected by the client while the server provider can provide additional code that can be reused by all clients. The Pengine concepts for web programming are rather different from anything else found in other environments.

If you want a safe approach, forking a new process for every session is probably the best way. Now, SWI-Prolog cannot fork if the process has multiple threads (because we cannot guarantee the state of mutexes). What we can do is start a second single threaded Prolog process that preloads all shared code and listens using a pipe to the main web server. If the web server creates a session it asks for the second process to fork itself and subsequently it talks to the new forked process in a similar way as the communication to the engine works in my gist example (except that we use a pipe to communicate)

I don’t think that is very hard to implement. The main disadvantage is that its scalability is much worse because a process requires a lot more resources than an engine. If a tenant is a company and companies do not trust each other, but they write the code that handles multiple users we can opt for a hybrid approach were we fork a process for each tenant and create engines inside this process for each user. Now, if the tenant makes sure its code adheres to the isolation requirements all is fine. If a tenant doesn’t adhere to these standards its users are not isolated, but they remain isolated from the users of other tenants.

From a web development perspective this is all pretty much similar as the gist, except that the some code may need to be in the main web server and some in the forked processes. That can be achieved using a suitable file structure, but we can be flexible as migrating Prolog code from one process to another is pretty much trivial.

It seems indeed that forking be the best and safest alternative.
Now, from a tomcat/Java point of view, tomcat has already the possibility to fork a process and to call inside that process an application (which chould be a lean swi-prolog application) - or to instantiate a “big” swi-prolog class having all inside, the interpreter … So a tomcat servlet could control this forking.

Do you think I could encapsulate swi-prolog in that way? Could you theoretically / practically provide (maybe there is already) a library from which the “big swi-prolog class” can be instantiated and used (right now I forgot in which language swi-prolog is realised, if not in Java, then shell programming will help (me)). Of course I do not intend to cause (you) work on this, unles this could be generally interesting.

See for an example fork based way to manage Prolog compute servers. You can load all common code along with the fork server, to make a servlet available quickly.

This assumes a Prolog client (included). If you want a Java client I’d rewrite the server to use JSON for exchanging queries and replies. There are zillions of things that can be added to this setup (resource limitations, non-deterministic answers, I/O forwarding, etc.)

Impressive - thank you a lot for this code. The code is prolog-centric and needs at least one prolog instance running. What if that instance breaks down?

( Of course I would prefer a Java code called and controlled by tomcat (using tomcat security) … I will study the use of this code however. )

Yes, you need one running. It barely does anything though, so it should be very reliable. Normally you’d start that under systemd or some other service manager and tell that to restart the service on failure.

Doing the fork in Prolog allows you do preload (large) background knowledge and anyway is a lot faster than starting a Prolog instance fresh and typically uses less resources as the multiple instances will share a lot of read-only data/program code.


It barely does anything though, so it should be very reliable.

well … for me reliability means other things. Anyway - supposed the servlet talks to that prolog instance which forks each time a process - in one forked thread what can be done please? Can the prolog kb be changed? If one user x change the kb in “his” forked prolog thread, the others still have an unchanged and (from x) unreachable prolog system with bound input/output they can change at their side? Tomcat will take care of the network security, but this one running prolog … is this the place where every forked process communicate or is it just to fork new ones? So then the servlet will have to talk just with a forked prolog thread (not with the common prolog one …) right ?

Hello Jan

  • a happy new year -
    Now that (my) lecturing is complete (for 2019) I have some time to dedicate to your nice prolog and to my issues of integrating it into a java tomcat 9. Re-reading what I wrote you maybe I guess I could not make me fully understood.

What I need (and would like to do) is the following secured prolog encapsulation:

Inside my tomcat java web application I would like to start upon some client buttons via javascript calls (but always at server side!) a tenant (session bound) instance of prolog in a forked process, in which the java code is putting commands and readings reactions (I/O) and giving these reactions back to the same session client. Think of a (tenant) private prolog shell listening to load and execute commands which come from an attached java program. I discovered JPL just a minute ago, donloaded the code (thank you) but I cannot find there a real example where a Java program starts / forks a private prolog process (in a kind of shell), then load some scripts and query some clauses. And I could not find the name of the jpl jar to bind with my java code. Maybe I am blind, any help would be appreciated.



I could find on my computer searching for “jpl.jar" a couple of files with that name. Then I tried to download jpl.jar from in any case I have troubles binding that jar with the rest of my java.
Normally I have no problem adding and using a jar for my projects - I simply add the jar to the WEB-INF/lib folder of the application and code in Java. With jpl.jar it seems it does not want to function as espected or assumed. For instance my eclipse wants to rename Query into jpl.Query and then tries to import the code from org.jpl7.Query - but at runtime it does not function (it does not find the class or jpl.fli.Prolog cannot be initialized) … Seems to be difficult … until it wants to run… Maybe I am using an old packaged jpl.jar - which one is the good one? (anyway In my java projects I have jpl.jar once! (so no ambiguity problems)).

The code:

public class PrologEngine {

**public** String create() **throws** IOException


	String xoutput = "PrologEngine starting ...";

	// create via fork a prolog process which never ends

	jpl.Query q1 =

		    **new** jpl.Query(


		        **new** jpl.Term[] {**new** jpl.Atom(“/…………/")} 


	jpl.Term x = q1.goal();

    **return** xoutput = x.toString();



In the following the exception (maybe you understand what can be wrong):

SEVERE: Servlet.service() for servlet [ACTIONS] in context with path [/XXX] threw exception [Servlet execution threw an exception] with root cause

java.lang.NoClassDefFoundError: Could not initialize class jpl.fli.Prolog


at jpl.Util.textToTerm(

at jpl.Query.Query1(

at jpl.Query.<init>(

at com.s2m.classes.PrologEngine.create(

at com.s2m.classes.ACTIONS.doGet(

at com.s2m.classes.ACTIONS.doPost(

at javax.servlet.http.HttpServlet.service(

at javax.servlet.http.HttpServlet.service(

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(

I set PATH to
export PATH=/Applications/$PATH

where the swipl app is.

Then I deleted jpl.jar from the WEB-INF/lib folder and added the swipl original external jar directly using eclipse’s java build path - “/Applications/” and the jar loaded. Again the not-found issue. This time getting a java.lang.ClassNotFoundException: org.jpl7.Query

Looks more like a chess party :wink:



Finally I got the solution, fixing paths after paths:

java.lang.UnsupportedClassVersionError: org/jpl7/Query has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0

This corresponds to Java 11.

I am using Java 8.

What do you suggest please? Can I have a version for java 8 please ?

Even using jdk 11 and after having entered the missing java argument -Djava.library.path=/Applications/ - I stuck in
Jan 03, 2020 12:43:35 AM org.apache.catalina.core.StandardWrapperValve invoke

SEVERE: Servlet.service() for servlet [ACTIONS] in context with path [/SVIZ] threw exception [Servlet execution threw an exception] with root cause

java.lang.UnsatisfiedLinkError: /Applications/ dlopen(/Applications/, 1): Library not loaded: @rpath/libswipl.8.dylib

Referenced from: /Applications/

Reason: image not found

Using SWI-Prolog (threaded, 64 bits, version 8.0.2) on mojave 10.14.6

That is not going to work using JPL. JPL embeds Java in Prolog or (for you more interesting) Prolog in Java. They are part of the same process and talk using the SWI-Prolog foreign language interface and Java’s jni interface. The result is (IMO) rather verbose and hard to manage, but does provide a low-latency and high-bandwidth interface between Java and Prolog. You can’t fork Prolog as that also forks Java and while I do not know about Java, SWI-Prolog with active threads cannot be forked (this could be fixes, although I’m not sure how easy that is). As your tenants are all talking tot the same shared Prolog instance, isolating tenants is hard to guarantee unless you only execute code that is aware of the isolation requirements and properly written.

If you want to achieve this, the best way is most likely to go the route I outlined: have a single Prolog server. If Java creates a session, contact the server to create a fork and setup a socket connection to Java. Now you can exchange commands (I’d first consider JSON as exchange language, but you can also opt for using the websocket protocol or Google protobufs, XML, …). Even Prolog is an option, but I generally advice against that as reliable parsing and generating valid Prolog is remarkable complicated and thus you need to setup a Java infrastructure similar to JPL to represent Prolog terms and implement read/write for that. If the session times out or is terminated you just send the Prolog instance a halt request and to be on the safe side you can add a similar timeout on the Prolog end to commit suicide if no new commands are read before a timeout. This approach is reliable, fast (depending on the how much data is preloaded into Prolog between a few microseconds and a few milliseconds) and safe (the OS ensures encapsulation).

JPL on MacOS is a bit complicated beast to get running. After installation you need to run in Prolog

?- jpl_config_dylib.

to fix the path dependencies of on the running Prolog image and location of Java on your system. This uses /usr/libexec/java_home to figure out where Java lives. If you want a different Java, make sure $JAVA_HOME is an environment variable with the Java home dir.

After that, restart Prolog and this should work without errors.

?- [library(jpl)].

Then you can try to setup the config using Eclipse. I know nothing about that.

Thank you Jan

unfortunately there is NO under ther darwin lib folder as I wrote - just a libjpl.dyn .

I am asking me why all this had/has to be so complicated to “cook” :wink: since OSX is basically a linux system (but in the hands of apple…) The code finally should totally run under linux and maybe inside a docker container - but I do prefere to develop stuff in OSX (until today with no surprises).

So JPL is not tenant safe (thank you for telling me) - I am not necessarily primarily interested in translating prolog terms to java structures (although this sounds maybe interesting if it is safe). I am rather interested - once this multi-tenant “issue” is solved to import RDF as basis for prolog computations and run the prolog machines, one for each tenant really separately.

I am really not sure about that. It can look like a Linux system if you look at it from the right angle because there is some overlap of the command line applications that run in user space. Even there however there is quite a bit of annoying incompatibilities.

The kernel is definitely not a Linux at all. Android would be an example of an operating system that actually uses a “Linux kernel” (if we don’t want too technical).

No, it is not. That’s a common misunderstanding. See e.g.