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

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 libjpl.so 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 libjpl.so 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.

Sorry. Most modules are .so, but for some reason the JVM insists on .dylib.

So, no. OSX is based on BSD Unix (I think OpenBSD). The most noticeable difference is that it uses XCOFF binaries rather than ELF binaries (on Linux) and these have quite different dynamic linking semantics. That hurts at the moment you need to link two systems with lots of dynamic libraries and installed independently. Good news is that life on Linux is easier. Your program should be fully compatible on both systems, but the steps you need to take to glue Java and Prolog together using JPL are different.

P.s. I found the built forgot to enable Java compatibility and thus the .jar files are compiled for the native Java installed on the build machine. Pushed a fix for that, so 8.1.20 should be fine.

That should all wok nicely using my proposal.

Thank you ver much :slight_smile: Jan, Boris and Pmouri - so I keep optimistic !!! I will dive into all that and come back in some days (weeks?) - have all nice days.

Hi Jan, thank you for that - although the prolog code is much more interesting, since I am java based, the JSON (communication) variant would be for me more suitable. Also I am thinking at how - for each tenant separately - to issue an interactive prolog session. What I mean by interactive: Creating/executing a prolog program using fail so that an (a priori unknown) set of answers could be generated and input/output to/from prolog could be handled by an application - hence shown in a web client bound to the session id.
Do you have any hints on that?

A complete environment for managing programs is of course provided by SWISH. Have a look at https://swish.swi-prolog.org. This also provides a client for Java. So, one option is to have a single threaded Prolog server with swish, shared RDF and whatever you want loaded. On a request for a session you ask that to fork and start a swish server at some (local) port. Now you can communicate using the Pengines protocol to give commands from Java and you have a full development environment that you can either make directly available to the tenant or modify/embed in the rest of the front end.

This is surely a bit of work to setup, but provides a lot of functionality out of the box. There are people around here that have the knowledge to setup this sort of thing.

1 Like

Just for the record. If you want to play with this stuff, use version 8.1.x. 8.1.20 will be released in a few days max. The devel version is currently a good idea anyway. It is way more stable and provides much better deployment support.

I’ll keep it in mind. Thank you Jan

Why in the official help page https://www.swi-prolog.org/search?for=fork_server is not delivering?
[probably the exact name of the code snipped you gave me has changed] - but so I am again in the rain … is this a mistake or the server functions should not be in the help page?

I have another problem, since the access to information is quite narrow (for me at the moment) I am trying to encapsulate swipl inside Java’s ProcessBuilder (pb). This works quite well up to prolog read() - prolog read() waits for terminal (standard) input - a term terminated by “.”. This prolog read blocks somehow when the external process pb is writing a term terminating by a “.” - what can be done to overcome this peculiarity?

??? That was a local predicate I gave in the GIST https://gist.github.com/JanWielemaker/d9837fb1858d76d5dfd9caa3851db057. Why would the documentation server know about that?

Possibly a missing flush for the output? If you are trying to encapsulate Prolog in Java to make creating a Prolog process easier I fear you are most likely just making things complicated if not impossible. Surely if this involves JPL. JPL is a complicated beast one should (IMO) only use when there are no alternatives due to required high bandwidth and low-latency communication between Prolog and Java. In other cases, first consider keeping them apart.

Where should one (me) get to the documentation of that “local” predicate? No documentation, no use. Would you use a predicate without knowing what it does and how it does it? I appear to me normal to look for some description about pieces you suggested. But of course this is half the price if 1) I do not read the documentation because there is no one about a “local” predicate (pls. define “local” predicate) and 2) I don’t know how to interface via JSON to prolog… unless by reverse engineering what is already there. … (hope I explained your ??? :wink: ) seems everything is beast here… :wink: hope to be able to conquer it sooner or later :wink: Cheers.

The point was simply that this was a small example; it is not library code. “Local” meant that it is just local to the small example. So it was not part of any distribution or package, just an example so that you can get started with your own code.

(forgetting for a moment that this was just a small example and so it is not reasonable to expect too much documentation for it)

Well well… if you are working with products from Oracle, or Microsoft, or Apple, maybe you’ve got a point (maybe). You don’t have the source code so you only rely on documentation and your own experiments and the vendor’s good will. With open source projects, you can always look at the code. So this is no longer a fair point.

1 Like

Start reading here:

https://www.swi-prolog.org/pldoc/doc_for?object=section('packages/http.html')

There is a section about JSON.

https://www.swi-prolog.org/pldoc/man?section=jsonsupport

Apple forked Free BSD to create OSX (creating launchd, which in turn inspired systemd, which created a huge nerd war in the Linux world…).

Both Linux and Free BSD are open source Unix versions with differences too subtle for my understanding.

An important difference is that the kernels don’t share source code (as far as I am aware) and have different lineages. It is important both from a technical and a political point of view.