Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to deal with shared-libraries for many web applications using the same libraries

We have a web application made in Java, which uses struts2, spring and JasperReport. This application runs on glassfish 4.0.

The libraries of the application are in the WEB-INF/lib folder, and also in glassfish are installed 4 more than uses the same libraries.

Glassfish is configured to use 1024mb for heapspace and 512m for permgen, and the most of the memory consumption when i use libraries per application is in the struts actions and spring aop classes (using netbeans profiler).

The problem we are having is the amount of memory consumed by having libraries in the classloader per application because is to high and generates PermGen errors and we have also noticed that the application run slower with more users.

because of that we try to use shared-libraries, put it in domain1/lib folder and found that with a single deployed application the load time and memory consumption is much lower, and the application works faster in general. But when we deploy the rest of the applications on the server only the first application loaded works well and the rest has errors when we calls struts2 actions. We believe that is because each application has slightly different settings on struts2 and log4j.

We have also tried to put only certain libraries on glassfish and leaving only struts2 in the application but it shows InvocationTargetException errors because all libraries depend the lib from apache-common and it dont matter if we put those lib on one place or another. Also if we put it in both places the application don’t start.

  1. there any special settings or best practices for using shared-libraries?
  2. Is there a way to use shared-libraries but load settings per application? or we have to change the settings to make them all the same?
like image 648
Aegis Avatar asked Nov 07 '13 16:11

Aegis


People also ask

What is the use of shared libraries in was?

Shared libraries are files used by multiple applications. Each shared library consists of a symbolic name, a Javaâ„¢ class path, and a native path for loading Java Native Interface (JNI) libraries. You can use shared libraries to reduce the number of duplicate library files on your system.

Are system libraries shared?

Most modern operating systems can have shared library files of the same format as the executable files.

What is shared library?

A shared library or shared object is a file that is intended to be shared by multiple programs. Symbols used by a program are loaded from shared libraries into memory at load time or runtime.


Video Answer


2 Answers

Is there any special settings or best practices for using shared-libraries? Is there a way to use shared-libraries but load settings per application? or we have to change the settings to make them all the same?

These are actually interesting questions... I don't use GlassFish but, according to the documentation :

Application-Specific Class Loading

[...] You can specify module- or application-specific library classes [...] Use the asadmin deploy command with the --libraries option and specify comma-separated paths [...]

Circumventing Class Loader Isolation

Since each application or individually deployed module class loader universe is isolated, an application or module cannot load classes from another application or module. This prevents two similarly named classes in different applications or modules from interfering with each other.

To circumvent this limitation for libraries, utility classes, or individually deployed modules accessed by more than one application, you can include the relevant path to the required classes in one of these ways:

  • Using the Common Class Loader
  • Sharing Libraries Across a Cluster
  • Packaging the Client JAR for One Application in Another Application

Using the Common Class Loader

To use the Common class loader, copy the JAR files into the domain-dir/lib or as-install/lib directory or copy the .class files (and other needed files, such as .properties files) into the domain-dir/lib/classes directory, then restart the server.

Using the Common class loader makes an application or module accessible to all applications or modules deployed on servers that share the same configuration. However, this accessibility does not extend to application clients. For more information, see Using Libraries with Application Clients. [...]

Then I would try:

Solution 1

  • put all the libraries except Struts2 jars under domain1/lib ,
  • put only Struts2 jars under domain1/lib/applibs,

then run

$ asadmin deploy --libraries struts2-core-2.3.15.2.jar FooApp1.war
$ asadmin deploy --libraries struts2-core-2.3.15.2.jar FooApp2.war

To isolate Struts2 libraries classloading while keeping the rest under Common Classloader's control.

Solution 2

  • put all the libraries except Struts2 jars under domain1/lib ,
  • put only Struts2 jars under domain1/lib/applibs, in different copies with different names, eg appending the _appname at the jar names

then run

$ asadmin deploy --libraries struts2-core-2.3.15.2_FooApp1.jar FooApp1.war
$ asadmin deploy --libraries struts2-core-2.3.15.2_FooApp2.jar FooApp2.war

To prevent sharing of the libraries by istantiating (mock) different versions of them.

Hope that helps, let me know if some of the above works.

like image 137
Andrea Ligios Avatar answered Oct 23 '22 06:10

Andrea Ligios


You can try to create what is known as a skinny WAR. Pack all your WARs inside an EAR and move all the common JARs from WEB-INF/lib to the lib/ folder in the EAR (don't forget to set <library-directory> in the application.xml).

like image 32
Philippe Marschall Avatar answered Oct 23 '22 06:10

Philippe Marschall