Dynamic loading of modules in Java - java

In Java, I can dynamically add stuff to classpath and load classes ("dynamically" meaning without restarting my application). Is there a known framework/library which deals with dynamic loading/unloading of modules without restart?
The usual setup, especially for web-apps, is load balancer, several instances of application, and gradual deployment and restart of new version. I'm looking for something else - application with several services/plugins, possibly single-instance desktop application, where disabling single service is cheap, but bringing down or restarting complete application is not feasible.
I'm thinking about typical plugin infrastructure, where plugins can be upgraded or installed without restarting application. Do I have to program that from scratch, or is something already available? Spring-compatible and opensource is a plus, but not a requirement.

You might consider running your spring application in an OSGI framework.
I believe the DMServer is a module-based Java application server that is designed to run enterprise Java applications and Spring-powered applications, based on OSGI
You can find more details in this Hello, OSGi, Part 2: Introduction to Spring Dynamic Modules article, in particular how to use Spring DM to dynamically install, update, and uninstall modules in a running system.
Note: when you speak about "plugins can be upgraded or installed without restarting application", OSGI is the first candidate framework that comes to mind.
It is all about modularization of applications into smaller bundles.
Each bundle is a tightly-coupled, dynamically loadable collection of classes, jars, and configuration files that explicitly declare their external dependencies (if any).

Perhaps the simplest approach is to load each plugin with it's own class loader. Then discard the class loader and create a new one to reload the plugin. You will want init() and destroy() methods in the plugin API to allow a chance for startup/shutdown type functionality.
This also has the advantage of isolating the plugins from each other.
A URLClassLoader is your starting point for this. The general idea is that you provide a XxxPlugin superclass that any plugin subclasses. Consider the example of Applet, which is essentially a GUI plugin (or Midlet, etc).

Related

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.
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?
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.
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).
I'd bet that placing the libs under lib/ or lib/ext won't resolve your performance issues. You did not write anything about the applications or server settings, like size of application, available Heap and PermGen space, but nonetheless I would recommend to stay with separate libs per app.
If you place the libs in server dirs, they will be shared among all apps. You will loose the option to upgrade only one of your applications to a new framework or to get rid away of any of them. Your deployment will be bound to a specific server architecture.
And you wrote it did not solve your problems, it even may raise new ones.
I would recommend to invest some hours into tuning the server. If it runs with defaults, allocate more PermGen and HeapSpace.
If this does not help, you should analyze in deep what's going wrong. Shared libs might be a solution, but you don't know the problem, yet. IBM offer some cool and free tools to analyze heap dumps, this could be a good starting point.
I came here in search of guidance about installing libraries that are shared among multiple applications or projects. I am deeply disappointed to read that the accepted practice favors installing a copy of every shared library into each project. So, if you have ten Web application, all of which use, e. g., httpcomponents-client, mysql-connector-java, etc., then your installation contains ten copies of each.
This behavior reminds me, painfully, of the way of thinking that motivated me to abandon the mainframe in favor of the PC; the thinking seemed to be "I don't care how many resources my application consumes. In fact, I'd like to be able to brag about what a resource hog it is." Excuse me, please, while I hurl.
The interface exposed by a library is an immutable contract that is not subject to change at the developer's whim.
There is this concept called backwards compatibility. If you break it, you create a new interface.
I know of at least two types of interfaces that adhere to the letter and spirit of these rules.
By far the oldest is the IBM System/370 system libraries. You might have Foo and Foo2, where the latter extends and/or breaks the contract made by the Foo interface in some way that made it incompatible.
From its beginnings in the Bell Labs Unix project, the standard C runtime library has adhered to the above rules.
Though it is much newer, the Microsoft COM interface specification enforces the same rule.
To their credit, Microsoft generally adheres to those rules in the Win32 API, too, although there are a handful of exceptions in that API. To a degree, they went backwards with the .NET Framework, which seems slavishly to follow in the footsteps of the Java environment that it so eagerly seeks to replace.
I've been using libraries since 1978, and my understanding was and is that the goal of putting code into a library was to make it reusable. While maintaining copies of the library code in each application eliminates the need to implement it again for each new project, it severely complicates upgrading, since you now have ten (or more) copies of the library, each of which must be updated.
If libraries adhere to the rule that an interface is an immutable contract, why shouldn't they live in a shared library directory, as do the Unix system libraries that live in its /lib directory, from which everything that runs on the host shares a single copy of the standard C runtime library, Zlib, and so forth.
Color me seriously disappointed.

Add Custom Mediator (Java Class) without restart

We often have Custom Mediators (Java classes) that are performing transformations or other things. Each time we want to change only one little thing inside the class, we need to restart the whole WSO2 ESB.
May the "custom mediator" approach is wrong, but we'd like to keep the java classes, but de-coupled from the whole server - like proxies or endpoints. (Our classes are inside a .jar in /components/lib)
How can a custom mediator or java class added to the WSO2 ESB without restarting?
<class name="my.domain.MyJavaClassThatMustBeUpdatedWithoutRestart"/>
You can create an osgi bundle from your class and then you can control the classes behavior from the OSGI Console. You need to start esb with -DosgiConsole option. You can find more information from this blog post.
http://lalajisureshika.blogspot.co.uk/2013/03/some-useful-osgi-commands-to-find.html
While starting up we make OSGI bundles out of the non-OSGI jars in components/libs.
So you must restart if you want to change the custom mediator jars.
As per the below coment explaining the answer,
WSO2 Products are running on an OSGI based platform. So if you change an OSGI bundle you can restart the bundle from the OSGI Console without restarting the whole server. Also the OSGI Container used by WSO2 is Eclipse Equinox OSGI Container. It provides the ability to add non-OSGI jars to product with the feature of, converting those jars in to OSGI Bundles. And that feature works only at the server startup. So if you want to add/change those jars you should restart the server. In runtime you can change OSGI bundles, but you can not convert non-OSGI bundeles to OSGI in runtime.

Using Spring without exposing the dependencies to the Client app

I'm writing a Java API for several clients, and would internally like to use Spring and it's several features, but I don't want to expose to the client my dependencies.
Is this possible?
So if my client uses a different version of spring would they be insulated from my internal Spring dependencies.
If so, would my spring dependencies be bundled internally inside my jar? As well as would a custom class loader be required by my client application?
I have heard you can use this through OSGI bundles, but I'm wondering if this would satisfy my requirement.
The clients of my API wouldn't be OSGI enabled or we have no current environment that utilizes OSGI bundles.
It is not really feasible, or desirable to do so. Why would you want to "hide" the dependencies? Would you also want to hide a dependency on whatever logging package you may be using (for example)?
If you have the dependencies in your implementation, then they are best published as it will cause a lot less grief on the part of users of your API since they will know what conflicts may exist before they even attempt to use your code.
Don't forget, your users are actually developers and I am sure that they would rather be aware of any landmines or requirements up front.
Edit - Regarding OSGi:
OSGi will definitely take care of your conflicting dependencies issues, but it also would rely on deploying in an OSGi environment, which you haven't mentioned is the case for your clients. In addition, it is still not recommended to "hide" those dependencies in a bundle. The very nature of OSGi allows those conficting depencies to cooexist in the same application.

Dynamically loadable and unloadable application modules in Java - how?

I'm writing a server application which makes use of external modules. I would like to make them to be upgradeable without requiring server restart. How do I do that? I've found OSGi but it looks very complicated and big for my task.
Simple *.jar files are ok, but once they are loaded, I suppose, I cannot unload them from VM and replace with another version on-the-fly.
What approach can you suggest?
It seems like OSGi is exactly what you're asking for. It can be complex, but there are ways to deal with that. Some of the complexity can be mitigated by using SpringDM or something similar to handle the boilerplate tasks of registering and consuming services in the runtime. Annotation-driven service registration and dependency injection really reduces the amount of code that needs to be written.
Another way to reduce complexity is to deploy the bulk of your application in a single bundle and only deploy the parts that need to be modular into their own bundles. This reduces your exposure to registering and using services from other bundles in the runtime as well as reducing the complexity of deployment. Code running within a bundle can use other code in the same bundle just as in a standard Java app - no need to interact with the OSGi runtime. The opposite of this approach is to break up your application into lots of discrete bundles that export well-defined services to other bundles in the system. While this is a very modular approach, it does come with extra complexity of managing all those bundles and more interaction with the OSGi runtime.
I would suggest taking a look at the book "OSGi in Action" to get a sense of the issues and to see some decent samples.
It would at least require you to define your custom classloader... I don't see how can this be simpler than just using Felix, Equinox, Knoplerfish or any open source Osgi runtime to do the task.
Maybe SpringDM is simpler...
What you're going for is definitely possible. I believe that you can unload classes from memory by loading them in a separate ClassLoader and then disposing that ClassLoader. If you're not wanting to go all out and use OSGI, I'd recommend something like JBoss Microcontainer (http://www.jboss.org/jbossmc) or ClassWorlds (http://classworlds.codehaus.org/). It's not too terribly difficult to write something like this from scratch if your needs are specialized enough.
Hope this helps,
Nate
If you follow the ClassLoader route (is not that difficult, really), I suggest each module to be packaged in its own jar, and use a different ClassLoader to read each jar. that way, unloading a module is the same as "discarding" the ClassLoader.
OSGi is not so complicated - using PAX runner with maven worked as a breeze.
Or implement your own ClassLoader and set it to JVM :
java -Djava.system.class.loader=com.test.YourClassLoader App.class

Allow for modular development while still running in same JVM?

Our current app runs in a single JVM.
We are now splitting up the app into separate logical services where each service runs in its own JVM.
The split is being done to allow a single service to be modified and deployed without impacting the entire system. This reduces the need to QA the entire system - just need to QA the interaction with the service being changed.
For inter service communication we use a combination of REST, an MQ system bus, and database views.
What I don't like about this:
REST means we have to marshal data to/from XML
DB views couple the systems together which defeats the whole concept of separate services
MQ / system bus is added complexity
There is inevitably some code duplication between services
You have set up n JBoss server configurations, we have to do n number of deployments, n number of set up scripts, etc, etc.
Is there a better way to structure an internal application to allow modular development and deployment while allowing the app to run in a single JVM (and achieving the associated benefits)?
I'm a little confused as to what you're really asking here. If you split your application up into different services running across the network, then data marshalling has to occur somewhere.
Having said that, have you investigated OSGi ? You can deploy different bundles (basically, jar files with additional metadata defining the interfaces) into the same OSGi server, and the server will facilitate communication between these bundles transparently, since everything is running within the same JVM - i.e. you call methods on objects in different bundles as you would normally.
An OSGi server will permit unloading and upgrades of bundles at runtime and applications should run normally (if in a degraded fashion) provided the OSGi bundle lifecycle states are respected.
It sounds like your team has a manual QA process and the real issue is automating regression tests so that you can deploy new releases quickly and with confidence. Breaking up the code into separate servers is a workaround for that.
If you're willing to restart the server then one approach might be to compile the code into separate jar files, and deploy a module by dropping in a new jar and restarting. This is largely a matter of structuring your code base so that bad dependencies don't creep in and the calls between jars are made via interfaces that don't change. (Or alternately, use abstract classes so you can add a new method with a default implementation.) Your build system could help by making sure that separately deployed modules can only depend on common interfaces and anything else is a compile error. But note that your compiler isn't going to help you detect incompatibilities when you're swapping in jars that you didn't compile against, so I'm not sure this really avoids having a good QA process.
If you want to deploy new code without restarting the JVM then OSGI is the standard way to do that. (But one that I know little about.)

Categories

Resources