user520288
user520288

Reputation:

Glassfish environment for multiple applications with common dependency

I have a question which I am struggling with. The problem is that I do not even know what exactly I should search for on google, so that's why I am asking for a short explanation here on SO.

Let's say that I have three projects: A, B and C. A is a dependency for both B and C. B and C are web-services for example, which can be deployed in Glassfish. In A, there is a class with a static field, let's say an int. When building project B, the static int has value 3. Then, we build project C but we change the value of the static int to 4.

The question is: when we deploy both B and C to Glassfish, do these applications run in separate "environments" where the the static int has different values in each environment (3 in env of B, 4 in env of C) or is there just one static int?

LE: B and C are both deployed in the same Glassfish domain. Glassfish version is 3.1.1.

Upvotes: 2

Views: 1126

Answers (2)

fdreger
fdreger

Reputation: 12505

The problem is that I do not even know what exactly I should search for on google, so that's why I am asking for a short explanation here on SO.

What you want to search for is "Classloader". Objects of this type are responsible for loading Java classes. Each class loaded by JVM is identified by both its fully qualified name AND the instance of classloader that loaded it. This means that in a single JVM you could have a couple of classes named exactly "com.example.Test", each loaded by a different classloader - and each of them would have its own static fields. What's more, the classes would be considered different at runtime: casting "com.example.Test" from one classloader to "com.example.Test" from some other classloader would end in a ClassCastException.

To avoid situation where you have multitude of common classes loaded multiple times (like java.util.List), classloaders are usually kept in a clean hierarchy. Each classloader knows its "parent", that is classloaders responsible for loading "more general classes". When we try to load a class (which usually happens "by name"), like "com.example.OtherTest", the current classloader tries to ask its parent if it is able to load it (and the parent in turn asks its parent, and so on). This way each class is loaded by the most general classloader that is able to load it (java.lang.String will be always loaded by the standard bootstrap classloader even if some other classloader has some different version available).

When you deploy a war, glassfish creates a separate classloader for it. The classloader knows how to load classes from WEB-INF/lib and WEB-INF/classes. Its parent is (or at least grandfather) the domain classloader, common for all applications. So before application classloader loads any class - it will ask Glassfish to do it.

The whole process is quite configurable and enables you to have just one copy of common libraries loaded into JVM (eg. if you put your libraries into - AFAIR - domain1/lib/ext, they will be available to the domain classloader, an ancestor of each application's classloader; or you could even put it in your JRE's lib/ext folder and have it available to the main classloader, that will load the classes for any application you run). In such case they will share static fields. Or you could have your libraries loaded by war classloaders, and have all the static fields "private" to your applications.

Upvotes: 2

If "A for B" and "A for C" are different, you need to create a deployment for both B and C each enclosing its own copy of A.

The simplest approach is most likely a separate WAR for B enclosing A_for_B.jar and a separate WAR for C enclosing A_for_C.jar.

Upvotes: 2

Related Questions