I have to write a Java library that will need to be embedded in various run-time environments (some web services, desktop applications, even possibly in an Oracle database JVM).
It is important that the library run in the JVM of the application that uses it (e.g., I can't just make all the apps call a web service that uses this library).
It is also important that every application running the library runs the same version of it, as the library will be enforcing business logic that must be applied consistently across the enterprise.
Finally, some of the applications using the library are customer facing and have demanding up-time requirements.
Goal: I want to load a Java library from a central network location, but also cache it locally, to be used in the event that that central location is unavailable
**Question: can I do this somehow by writing a custom class loader that will search first on a network URL and, if found, load the class and save it locally and, if not found, load a previously locally saved version of the class? **
I don't know everything about classloaders and I am concerned about a few things. The location of the locally saved (cached) classes would probably not be in the CLASSPATH of the JVM. Would that be a problem? What other factors would make this approach problematic / unworkable?
Related
I work on an application with several microservices (modules). I defined datastore indexes in root application (which is containing just only those cfg files like datastore-indexes.xml and queue.xml etc). I see those indexes "serving" in console. [edit] so my fault i broken query earlier so question changes little. What is best strategy with mentioned cfg files in multi-module appengine app?
The datastore index configuration is one of the several app-level configurations, shared by all services/modules in the app and which can be deployed independently from the services themselves. In fact it's recommended to first deploy the indexes configuration, let GAE get those in Serving state (which may take a good while, depending on the number of entities that need to be indexed) and only after that deploy the app code needing those indexes.
For deployment on GAE purpose it doesn't really matter if the index configuration is located in a particular service or in the root of the application, as long as it's deployed from that location.
However the local development server may have trouble running a particular service without the index configuration in that server's directory - I suspect that's what causes you grief. To address this in the DRY spirit my preference is to have a master copy of the configuration file in the app root directory and symlinks pointing to it into each of the services directories.
Things get a bit more complicated because the Java GAE uses the datastore-indexes.xml configuration file while the other languages use the index.yaml file, with different formats. Java also supports the index.yaml file, but I'm not certain if that's equally well supported in the development server, IDEs and/or other local development tools.
If all your modules are Java-based you should be OK. But if you have a mix of languages you'll probably have to try to share an index.yaml equivalent.
If that doesn't work and you're forced to use both files, each symlinked into the respective language service dirs, you'll have to make sure the index configs in the 2 files are consistent, otherwise you risk breaking some of the services.
Potentially of interest: Can a default service/module in a Google App Engine app be a sibling of a non-default one in terms of folder structure?
I'm developing container-like application on Java which can host another Java-based applications (like Google App Engine). Currently I'm using Maven Assembly Plugin to assemble the hosted applications into one super-JAR with all the dependencies, but it looks like a bad practise.
Is there some libraries or tools to provide the dependencies at a runtime? I mean, I want to make a JAR only for hosted component-specific classes, without any dependencies, and store the dependencies list inside this JAR (in pom.xml or somewhere else). Host application will read this manifest and load required libraries to runtime. Is there any ready solutions?
You may have trouble with a tool like this; Java can load things dynamically at run-time too. This may work for you though: http://depfind.sourceforge.net ...
If you really need to get the size down, you may use the verbose flag in the java vm to see all the classes that are loaded. You will have to execute all the code to get the classes as they are loaded only when used (and loaded only once). Further, it is uncommon, but different classes may load depending on the platform.
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.
Due project requirements, I need to create a webapp that, when executing, will allow some users to upload zip files which are like small apps and will contain .class files, resources (images, css, js, ...) and even lib files. That zip file is almost like a war file.
Any way to code it easily? AFAIK I think I know how to code the custom ClassLoader to load classes from inside the zip file ( Java - Custom ClassLoader - trying to load a class using class file full path ) and even code the resource retrieval when requested by the browser but no idea of how to execute JSP files which will be inside the zip file or load the jar lib files inside the zip file.
EDIT: the webapp must manage applications loaded, there is no way to implement this as answered below because the webapps need the "master" webapp to live. Also that "master" webapp allows versioning of applications. The user will be able to upload a new version and upgrade to it and even do a downgrade if the new version starts to fail.
There is no easy way to do this. It's a lot of work. Classloaders are very finicky beasts. Arguably the bulk of the work of creating something like Tomcat is wrangling the class loaders, the rest is just configuration. And even after all these years, we still have problems.
Tomcat, for example, is very aggressive on how it tries to unload existing webapps, using internal information of the Java class libraries to try and hunt down places for class loader leaks, etc. And despite their efforts, there's still problems.
The latest version of Glassfish has (or will have) the ability to version application deployments. You might have good luck simply hacking on Tomcats internal routing and mapping code to manage versioning.
If you're running an EJB container, you could put your core services in the EJBs and let the WARs talk to them (you could do this with web services in a generic servlet container, but many EJB containers can convert Remote semantics in to Local semantics for calls in to the same container).
You can also look at OSGI. That's another real pain to manage, but it might have enough granularity to even give you versioning, but none of your users will want to use it. Did I mention it's a real pain to manage? We do this for dynamic loading of web content and logic, but we don't version this.
If you must have everything under control of a single WAR, then your best bet is to punt on Java and instead use a scripting language. You tend to have a bit more control over the runtime of scripting environment, particularly if you DON'T let them access arbitrary Java classes.
With this you can upload whatever payload you want, handle all of the dispatch yourself to static resources and logic (which means you get to handle the versioning aspect). Use something like Velocity for your "JSP" pages, and then use Javascript or whatever for logic.
The versioned environment can be pain to pull off. If you don't care about doing it atomically, it's obviously easier. If you can afford "down time" (bring v1 offline then bring up v2), it's a lot easier. If you're uploading the full contents of each version, it's really easy. My system allowed incremental changes and had copy-on-write semantics, so it was a lot harder. But I didn't really want to upload several Gb of media for each version.
The basic takeaway is that when dealing with Classloaders, there be dragons -- nothing is easy with those and there are alternatives that actually get code in to production rather than creating scars and pissed off dragons. Using a scripting language simplifies that immensely. All the rest is dispatch, and that can be done with a filter or servlet.
You WILL get the great joy of reimplementing a solid chunk of the HTTP protocol doing this, that's always a treat as well since the servlet container doesn't really expose that functionality to you. That is, you'll want to do that if you want to be a good citizen on the web. You could always just continually shove content down the clients throat, caching and proxies be damned.
You could manually create a WAR-like structures inside your web container webapps directory and put classes, JARs and JSPs there.
Given that hot redeployment is enabled in your web container it would automatically designate a separate classloader to this new web application that it finds.
In most cases web containers consider any folder having a WEB-INF subfolder containing a valid web.xml file to be a web application. You can restrict access to this new webapp by modifying its context configuration, located in META-INF/context.xml in case of Tomcat.
Controlling hot redeployment, classloader policies etc is dependent on the type of your web container, but I hope your is not worse than Tomcat which could handle all of that.
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.)