On Portability

I’m primarily (as always) talking Java, here. This post has a larger purpose but I’m not there yet. If all goes according to plan this post will make sense with some others to follow. At the moment it probably doesn’t make much sense. If that’s your thing, read on. You may be interested in the prior post in this series.

What is portability?

“Portable” just means capable of being carried. If you can pick it up and put it down, it’s portable. If you can take it from one “place” to another, it’s portable. My knapsack is portable. My piano is not, at least by me alone. Nor, really, is my crushing sense of self-doubt, but that’s another story.

Unless you’re just waving your hands, in computers and software when you’re talking about portability you have to talk about where the carrying is happening. Usually the word “across” or “between” is involved: A program might be portable across operating systems; a framework extension might be portable across different implementations of the framework; and so on.

In computers and software, we also usually add concepts of functionality and immutability to this. An application or a binary or a script is portable across computers or environments if, when you pick it up from one computer or environment and put it down on or into another computer or environment without changing it, it still works or can work. A pure Java application is portable across operating systems (or should be) because assuming you have java lying about at the destination you can pick up your CatsLOL.class file from a Windows computer and put it down on a Linux computer and run it in the same way without changing it. A binary resulting from a compiled and linked C program may not be (and usually is not) portable from one operating system to another.

A software component (like a library or a jar file or an individual Java class that is not a program) is also portable, even if you’re not switching operating systems or languages. You can pick a component up and put it (or a copy of it) down in multiple applications and incorporate it that way. In some sense you have “carried” it from wherever it was to several different destinations without changing it. This can happen even if you leave it in place: dynamic loading of libraries and classes is kind of a form of carrying, if you look at it right; the program doing the dynamic loading imports the library or class, thus notionally carrying it from one place to its own address space. “Reusability” is another (awful) word for this, along with other real winners like “composability”.

There are other sorts of more abstract things (let’s restrict ourselves to the software industry) that can be carried from one “place” to another and used without modification. If I leave one employer and go to another, I take my brain (hopefully) and experience with me, or at least the parts that are not signed away to the former employer somewhere. Publicly available stuff I learned from books, videos, websites, reference manuals and even certain source code may be portable from one work environment to another and I may be able to get up to speed more quickly as a result.

Things can be more or less portable. Sometimes something is 100% portable provided that the new environment it is being carried to is juuuuuuust right. If it is, then you put the thing down, it plugs into the new environment and runs exactly the same way as it did in the old environment. A pure Java program is a good example of this. A Java program that relies on a native library, by contrast, may find in the new environment that the environment-specific native library it needs for that environment is missing. If that library is put in the right place, then everything works. Another Java-centric example is: a Java framework extension or participant may be more or less portable depending on which features of the framework it uses or extends and how likely those features are to exist across the environments the Java framework extension or participant might be ported to. Then, even more abstractly, my knowledge of the JAX-RS API is fully portable from one job to another to the extent that the new job mandates proper use of the JAX-RS API. My knowledge of C++, on the other hand, probably isn’t very portable from one job to another because C++ permits lots of flavors and styles and maybe the old job and new job feature completely different styles of C++ programming. Also I’m joking about my knowledge of C++. So is everyone else.

To talk about software portability, particularly application portability, you often have to talk about platforms and platform implementations, because often what you’re really saying is that a given application is portable across a given platform’s multiple implementations. So then: an application is fully portable across platform implementations to the extent that there is more than one implementation of that platform and it doesn’t matter which platform implementation you pick to run it. Pick it up from one platform implementation; put it down in another: did it run? It’s portable! Congratulations! I probably didn’t write it.

So is a Jakarta EE application fully portable? It can be. If your application follows the platform specification, then you know it will (at least theoretically) run on platform implementations A and B in exactly the same way. If it uses features from one platform implementation, then you cannot necessarily pick it up from platform implementation A and run it unchanged in platform B, because platform B might not have those features.

Is a CDI SE application fully portable? This is sort of a nonsensical question, because CDI SE is not really a platform, but a framework. Regarding application portability, therefore, the answer is no. Now, certainly a CDI SE component (an extension, a bean, etc.) can be portable between CDI SE implementations and can be reused in various CDI SE applications: it can be picked up and carried from one CDI SE program and repackaged into another CDI SE program. If it uses Weld APIs, though, for example, then it is not fully portable across CDI SE implementations (like OpenWebBeans).

Is a Spring application fully portable? Yes and no. A Spring application packaged as a fat jar is just a Java program, so yes, you can port it from one Java environment to another, but given Java’s program portability promises this is almost tautological. Or, if you like: there aren’t two implementations of the Spring platform. From that perspective, therefore, a Spring application isn’t portable because there’s nothing to port it to. A Spring program packaged as a .war file, on the other hand, could conceivably be fully portable across Jakarta EE platform implementations provided that it carries all of its baggage with it (i.e. a Jakarta EE server will almost certainly not have any Spring libraries preinstalled). At this point, though, it just collapses into being a Jakarta EE application, so see above.

Is a DropWizard application portable? No. There’s nothing to port it to. There aren’t two implementations of a hypothetical DropWizard platform.

Is a Java application portable? Well, yes, but trivially so, and at a different sort of level. You can indeed run a Java program on different operating systems, and Java is a platform, so therefore a Java program is portable across operating systems. But given that we’re talking about portability across platforms, this foundational level of portability isn’t very interesting for this article.

Is a MicroProfile application portable? No, because there is no such thing as a MicroProfile platform, so there’s nothing to port it to. There are things that use MicroProfile APIs and even implement them but there’s no standard way to make some kind of hypothetical MicroProfile application and somehow run it in all of them.

Is an arbitrary binary portable? No; we’ve already covered that above.

If I make a binary using GraalVM’s native image facility, is the resulting binary portable? No, for the same reasons.

Is a Quarkus application portable? No; it’s just a binary. There’s nothing to port it to.

Is a Helidon SE application portable? No; it’s just a Java program that uses some libraries. There’s nothing to port it to.

Is a Helidon MP application portable? No; it too is just a Java program that uses some libraries, some of which happen to be partially specified. There’s nothing to port it to.

Is an OpenLiberty application portable? To the extent that it is a Jakarta EE application, yes; to the extent that it is not, no.

Is a Payara application portable? Same answer: to the extent that it is a Jakarta EE application, yes; to the extent that it is not, no.

Is an Oracle WebLogic Server application portable? Same answer.

OK, there are a lot of “no”s above. That’s not to say component and knowledge portability isn’t in play across the board. Some arbitrary examples:

  • A CDI component can be portable between CDI SE-, Helidon MP-, MicroProfile- and Jakarta EE-based applications
  • A Spring component can be portable between Spring applications
  • A JAX-RS resource class can be portable between DropWizard, Helidon MP, MicroProfile- and Jakarta EE-based applications
  • A component that uses org.eclipse.microprofile.config.Config is portable to any library or application that has MicroProfile Config available to it

…and so on.

More to come that may tie back to this article.

On Platforms

I’m primarily (as always) talking Java, here. This post has a larger purpose but I’m not there yet. If all goes according to plan this post will make sense with some others to follow. At the moment it probably doesn’t make much sense. If that’s your thing, read on. You may also be interested in the next post in this series.

What is a platform?

If I have one library with one class in it, with one function, do I have a platform? What about two functions? Two classes? Two libraries?

In my opinion, it depends on what it does.

Maybe I’m naïve, but I think a platform has to have a definition of what a packaged application looks like, a way to create such a packaged application (or at least verbiage about how to do it), and a way to run a packaged application that is handed to it. It may or may not also include a framework or libraries that the application may or must use.

You write and package an application to run on a platform, optionally (or not) using the platform’s facilities, and the application and the platform are distinct entities and have notionally different lifespans (that may of course nevertheless line up).

How the packaged application is expected to look and how it runs is dictated by the platform. Also, in most cases, but I suppose not all, a platform dictates how the application must look but not how it is produced.

So Docker, for example, is a platform, because, among other things, it tells you what a packaged application is, one way among several to package your application (docker build) and how to run it (docker run). Docker itself doesn’t really include any kind of framework that your application would use: your application is responsible, wholly, for doing whatever it wants to do. Here you can start to argue semantics about things like volume mounts and whatnot if you so choose, and if you do that I will start checking my phone and waiting for you to leave.

Is Kubernetes a platform? Unquestionably, it seems to me, by the same logic. (Also, anything with that many metric tons of YAML is probably a platform by fiat, or at least a ZIP code.)

Jakarta EE (and Java EE before it) is a platform because it tells you how to package your application (mvn {war plugin incantations}) such that a very specific ZIP file with a very specific filename suffix is created, or at least what an application so packaged must look like, and how to run (deploy) it. Well, hmm; no, it doesn’t really tell you how to run such an application, although it does say that any compliant Jakarta EE implementation must allow the user to perform a deploy operation on a standard packaged application. So more accurately: any given Jakarta EE implementation is a platform: you hand it a standard application, and its tooling can run that application.

Is CDI SE a platform? No. It is a framework. A framework is a library that, should it be poked through some other means, will arrange for your framework extension or participant to be called back (and hence started or poked, whatever that might mean, as well). CDI SE will look for certain classpath resources, but that’s not really packaging, exactly, and you can turn it off anyway, so ultimately you are the one doing the starting or poking of the framework and telling it what, in turn, to start or poke itself. Once you take care of that one way or another, your CDI SE framework extension or participant (your application) will do whatever the framework says it should do. So: framework yes, platform no.

Is Spring a platform? Yes and no. It is probably fundamentally a framework by the same logic, plus a collection of useful libraries you can use outside of the framework, plus some other stuff, plus a grand piano, some lead shot, the kitchen sink, a bank safe, and the fluff found in your front pockets. It also however does define a packaging format: if you build your Spring application a certain way, an executable archive pops out the other end that can be run by the Java platform (which also relies on a very complicated custom classloader embedded into the tail end of the ZIP-formatted archive by Spring!) or by a suitable Jakarta EE web container. So in that sense that part of Spring is a platform. On the other hand it leans on Java itself to do the heavy lifting if you execute one of its fat (and I do mean fat!) jars, so the recognizing that there is a Main-Class that has to be executed is done by Java itself, not by Spring.

Is DropWizard a platform? No, not really. DropWizard, like Spring, is a collection of libraries it defines and, unlike Spring, those from other places. It recommends, but does not define, various packaging formats. It wants you to run your program as a plain old Java program. Notably, DropWizard, while strictly speaking is probably a framework, delegates to other frameworks (like Jetty) to do the heavy lifting. Bottom line: not a platform, but a collection of useful libraries and frameworks.

Is Java a platform? Yes. It defines how you package your application and how such packaged applications are run. Using the same command line tool (java) you can run several different applications (executable jar files, exploded class directories, JPMS modules) depending on what you supply to the tool. (Also Java is obviously a collection of useful libraries!)

So is Java running a program that is a Jakarta EE implementation that deploys a Jakarta EE application two platforms? Yes, but in that picture presumably only the Jakarta EE implementation would be the platform of interest.

Is MicroProfile a platform? No. It is a framework as currently constituted, kind of. Actually, it’s not even really that, since there’s no entry point to a MicroProfile application, so no real defined way to poke it or start it. Like DropWizard, it relies (exclusively) on other frameworks (like JAX-RS) to do the heavy lifting, which do define such entry points. Nor is there a notion of a MicroProfile application that you start in any way. Nor is there a notion of deployment. Nor is there any common way to package a MicroProfile application even if there were a notion of what one is. Instead, I suppose it is a collection of useful libraries, and in some cases only parts of useful libraries, where the other parts are off-limits in some currently unspecified way. To use the language of Jakarta EE, it is, as currently constituted, “little more than bundles of APIs with few or no tie-ins” to a (nonexistent) larger platform. Maybe this will change.

If I have some arbitrary executable binary in my hand and I ask my computer to run it, is there a platform involved? Of course at some level there is, but I personally stop here, so therefore, dear reader, you will too: yes, a Unix system is a platform that runs, say, ELF executables, but in that parlance I guess I would be interested only in ELF executables that run other packaged applications. So, for this discussion, no, if I have an arbitrary executable (such as a compiled and linked C program) that just runs and does its thing, it is not a platform.

If I make a binary using GraalVM’s native image facility, is the resulting binary a platform? No (unless I’ve deliberately created a binary to run well-defined packaged applications of some kind, of course). See the logic above.

So is Quarkus a platform? No, because it just results in single purpose binaries. Quarkus is, really, a kind of compiler, I guess.

Is Helidon SE a platform? No; it’s a collection of libraries.

Is Helidon MP a platform? No; it’s a MicroProfile implementation and you’ll see above that MicroProfile isn’t a platform.

Is OpenLiberty a platform? Weirdly, although they define a runtime that can run well-defined packaged applications, they define themselves as a framework. I disagree; they are a platform: you deploy a well-defined packaged application to a simple server. Platform all the way.

Is Payara a platform? Yes. Depending on the product in question, it is either a Jakarta EE implementation of some kind (and hence a platform; see above) or defines a way of running applications (it is a MicroProfile implementation, and although as noted above MicroProfile is not a platform a runtime that defines a packaging format that happens to use MicroProfile’s useful collection of libraries is thus itself a platform).

Is Oracle WebLogic Server a platform? Yes; among many other things it is a Jakarta EE implementation.

More to come that may tie back to this article.