Updating WLS_HOME/server/lib contents without a restart - java

Does anyone know how to update the content of a WebLogic Server's WLS_HOME/server/lib/ folder without having to restart it?
A colleague of mine did a deployment which involved an updated .jar file that was used by all the .ears in the user_projects directory, so he decided to place it in WLS_HOME/server/lib. Whilst the web apps he deployed to user_projects deployed ok, we noticed in the server log it was getting repeated NoClassDefFound exceptions for classes we knew were in the updated .jar - and it didn't pick up the new classes till after a restart.
I need ideally to be able to deploy new shared libraries to this /lib folder without having to restart the server as that involves an outage.
Does anyone know how to do this?

This is not possible. You should move to shared Java EE libraries if you need more flexibility. For your current situation, the only thing you can do, provided you have a clustered environment, is to do a rolling restart of the instances to avoid downtime.
From Understanding WebLogic Server Application Classloading :
WebLogic Server includes a lib subdirectory, located in the domain directory, that you can use to add one or more JAR files to the WebLogic Server system classpath when servers start up. The lib subdirectory is intended for JAR files that change infrequently and are required by all or most applications deployed in the server, or by WebLogic Server itself. For example, you might use the lib directory to store third-party utility classes that are required by all deployments in a domain. You can also use it to apply patches to WebLogic Server.
The lib directory is not recommended as a general-purpose method for sharing a JARs between one or two applications deployed in a domain, or for sharing JARs that need to be updated periodically. If you update a JAR in the lib directory, you must reboot all servers in the domain in order for applications to realize the change. If you need to share a JAR file or Java EE modules among several applications, use the Java EE libraries feature described in Creating Shared Java EE Libraries and Optional Packages.

Related

multiple versions of javamail jar causing NoSuchProviderException

I have a standalone library ( jar file) that is added to the application server classpath to monitor all the running applications in the JVM and send email when some issue happens.
the jar file have all the dependencies bundled in the jar (using the maven-shade-plugin) including the javamail jar file.
When one of the other webapplications in the appserver have javamail as a dependency, some dependency conflict happens with the javamail in my jar file and I get an exception
MessagingException :javax.mail.NoSuchProviderException: No provider for smtp
How can I solve this conflict knowing that I can't modify the running appplications. I only have control over my jar file.
Edit:
I debugged through the javamail API. and I found out that the javax.mail.Session construct a new object of type com.sun.mail.smtp.SMTPTransport using reflection and pass two parameters to the constructor, but rather than using SMTPTransport located in the same jar file it tries to use SMTPTransport from the other mail.jar located in one of the deployed apps.
In tomcat 7, by default web applications will look first for classes on this order:
first on WEB-INF/classes
then inside jars in WEB-INF/lib
and if the class was not found only then in YOUR_SERVER_HOME/lib
Then on the system classloaders, as described here
Class versions from other WARs (on classes / WEB-INF/lib) cannot be visible from inside another WAR.
Can you let us know of further info that could help track down the problem:
what does the standalone library do in more detail, how does it monitor the other applications?
how is the standalone library added to the server classpath? Is it copied on YOUR_SERVER_HOME/lib, or is a folder added to the server classpath via shared.loader or common.loader properties of catalina.properties
does each WAR application provide it's own mail jars on WEB-INF/lib, or is the library published at the server level as a JNDI resource such as mentioned here on section Install the JavaMail libraries
Is any of the applications in the server NOT running in the default classloading mode that I mentioned above, and is using delegate = true (meaning it will look on the server first and only then on the WAR) ? here is how this would be configured, check for a Resource element in the context.xml or server.xml
Some suggestions for possible solutions:
Install JavaMail on tomcat 7 as a JNDI resource following the installation instructions here on section Install the JavaMail libraries. Have all applications use the JNDI resource as in the tomcat docs, and remove java mail from the standalone library using a shade plugin exclusion. This will always work and it's the most recommended solution.
If you are using Java 7, try to use JHades to troubleshoot the classpath of the different applications. You can do static analysis on the WARs for duplicate classes, or view what are the versions used at runtime of a given class, and which other versions are available.
Since there is no control over the deployment settings of the other applications or their contents, use of JNDI, etc., a solution that will work for sure in all environments and with any application is to refactor the tool so that it does not require mail.jar to be installed on the server. The tool can write an email request to for example a file or a database table, and another WAR deployed on the server would poll the table file and send the mail. Or a bash/bat script is called that itself sends the email on a separate java process.
Performance analysis tools such as Dynatrace are based on JVM agents and use a similar mechanism that does not need the introduction of libraries at the server level, the agent collects data and sends it to a collecting process that stores it somewhere for further analisys, treatment such as send alarms via emails, etc.
Hope this helps, in general I don't see any way to deploy libraries to a EE server and be sure that they will never cause problems to any application on different server types and different application classloading settings.
The best is probably adapt the tool so that it relies on a minimum of libraries deployed on the server, breaking it up into separate modules with only the collecting module running on the server or look into alternatives such as Dynatrace.
I'm not familiar with the maven-shade-plugin. Does it package the original jar files in a new jar file? Does it extract the contents of the original jar files and insert the contents into the new jar file? If the latter, it may only be including the class files and not the resource files in META-INF that configure the JavaMail providers.
Of course, the best approach would be to arrange for only one copy of the JavaMail jar file to be included in the server's classpath.
Upgrade the JavaMail version included with Tomcat 7 to JavaMail to 1.5.3 which contains the fix for Bug K6668/E144 -skip unusable Store and Transport classes. You can download the latest snapshot and official releases from the JavaMail reference implementation home page.

How are Java applications deployed in the "real world"?

As a novice to the world of Java programming, this question has always boggled my mind. I first believed that all Java files were compacted into applets and then ran, but I soon realized that this isn't always the case. Could someone explain to me how we actually interweave our Java applications into a real product of everyday life?
TL;DR: How do we implement our code for practical usage?
It depends on the application. There are many options depending on how you want your users to use your app. Usually it's packaged as a jar or a specialized jar (war, ear).
In theory, you could zip the raw directory structure with your .class files in it and provide a shell script/instructions that run the java command for the user. I don't recommend this because it's kind of unprofessional and requires you to maintain a shell script for each OS you want to be able to run the program on.
Jar files are used to package libraries but you can also have a manifest file in it that says, "When someone double clicks/executes this, run this class". That class can start up a GUI or be a headless task that responds to the parameters, etc.
You can have applets, like you said. These programs are run in the user's browser.
You can have a war file, which is a way to package a web application. You give this to a web server and it knows how to deploy it so that you can visit the web pages. An example web server/container is tomcat or jetty.
You can have an ear file which can contain other war files inside it. This is used for applications that need other parts of the javaee functionality (ejbs, jms queues, etc.). An example of an application server is jboss or glassfish.
There's also java web start apps. These are apps you can run by visiting a webpage, but they get downloaded to your computer and run on the user's computer (instead of on the server's backend, like in a war/ear).
There's also javafx. I don't know anything about that though. By skimming the FAQ, it appears to be Java's answer to Adobe's Flex. You configure UI components with an xml configuration. I'm not sure what format JavaFX apps use, but it does say, "Deploy on the desktop or in the browser".
As Sotirios Delimanolis mentioned in a comment below, you can build these files with build systems like Ant or Maven. You can also build them "by hand" with the tools that come with the java/javaee sdk. For example, you should have a jar command in your path if you installed the sdk. Here are some details of these build systems:
Maven
High level (you tell it what to build, not how to build it)
Much more than just a build system. It also has dependency management, etc.
Opinionated (it uses convention over configuration, each config file generates 1 artifact, etc.)
Ant
Low level (you tell it how to build things)
Flexible
Config files can do whatever you want, build as many artifacts as you want
Easy to learn
SDK tools
Always up to date. EG: Very rarely, maven/ant may not be able to set a configuration option
Difficult to remember commands
Very low level
By itself, not repeatable (EG: unless you build a script, you will have to type the jar command yourself each time)
Applets never really caught on and are very rarely used nowadays.
Simple applications can be deployed as "executable" JAR files , which are basically ZIP archives with additional metadata that tells the JVM which class contains the main method to run. They can be run on the command line using the -jar option, or in most desktop environments by double-clicking (this requires a JVM to be installed as well).
Desktop applications can be deployed via Java Web Start or installers like IzPack or Install4J, but Java desktop applications are not very common either.
Most Java software nowadays runs only on servers (web servers or app servers). They are typically deployed as WAR or EAR files, which are also ZIP archives containing classes and other resources. These applications then run inside a server component following the Servlet or EJB standards.
If the application is mean to run on a client, it is packaged as an executable JAR, then further packaged as an Application Bundle (Mac), maybe wrapped in an exe (Windows), or paired with an executable script that will launch the JAR and set any required VM arguments.
If it is part of a web application, then it will be packaged as a WAR or EAR and placed into the appropriate location on the web server.
If it is simply a library, then it is usually packaged as a JAR (non-executable) and distributed as such for integration into larger projects.
applets and then ran, but I soon realized that this isn't always the case
Actually, applets are rare nowadays and their use is discouraged.
Create an executable jar, a war which is dropped into a web server or a library that is used by another project that is one of the previous two.

Can we update a jar / war file in a deployed server and then reload the new jar / war file?

Can we update a jar / war file in a deployed server and then reload the new jar / war file ?
if so how simple we can achieve this, and please if possible list web servers which support this feature.
Yes.
All major Java EE Servlet containers support this. All that I've worked with anyway, which includes Glassfish, Tomcat, WebSphere, WebLogic and JRun.
I haven't used the other Oracle container, but I would think it does too.
That said, none of them support it all that reliably (they'll detect most changes, but there are certain types of class changes that will always require a restart), unless you're using JavaRebel underneath.
Just by copying the 'war' file in the Server domain folder will automatically deploy it. I have done it with glassfishv3.1
The path for windows is C:\Program Files\glassfish-3.1\glassfish\domains\domain1\autodeploy
Once pasted another file gets created automatically [if the server is on] in the same directory
For the editing purposes the 'war' file can be opened with programs like WinRar or WinZip
Just open the files that you want to change and save it when the winrar asks for it.
Both Tomcat and Jetty will support a hot deploy. They simply monitor the deploy directory for changes, so you can just copy the .war file into that directory, and the server will undeploy/redeploy.
JBoss. Just drop in the files in the correct location.

Deploying a Spring-based WAR with its JAR dependencies externalized

I have a Spring app that has a lot of dependencies (18 megabytes of JAR files..) - Now, when I am testing on the remote Tomcat 6.0 server, I'd like to not have to upload that 19 megabytes of dependencies, and just upload the classes. Pretty simple, right?
I can't get the damn thing to work.
I'm using Eclipse 3.4, and if in Java Build Path->Order and Export I remove the export of all of the dependencies, I get a nice small WAR.
So here's what I tried:
I uploaded all of the libs to the server, and stuck them in common/lib in Tomcat. The directory didn't exist, so I created it and modified catalina.properties:
shared.loader=${catalina.home}/common/lib/*.jar
I've tried a bunch of other configs, but none worked. Restart the server, deployed war fails to start. Specifically:
SEVERE: Error configuring application listener of class org.springframework.web.context.ContextLoaderList$java.lang.ClassNotFoundException:org.springframework.web.context.ContextLoaderListener at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1
It's dying trying to load the Log4J listener, which it can't find in its classpath. The spring lib that listener is in is in common/lib.
Also - when I deploy the full 18 megabyte war, it works just fine. Everything inits and the app starts. Of course it works fine locally as well.
Oh - and I've replaced the hardcoded logging JARs with the ones out of the extras folder to allow Log4j to work.
Any help here? I have no idea why this isn't working.
"I have a Spring app that has a lot of dependencies (18 megabytes of JAR files..) - Now, when I am testing on the remote Tomcat 6.0 server, I'd like to not have to upload that 19 megabytes of dependencies, and just upload the classes. Pretty simple, right?"
I don't understand this - 19MB is not a lot. You'd be much better off just packaging a WAR and be done with it.
I recommend that you do your testing locally on your own identical Tomcat instance, get it all working, and then deploy the WAR to the remote Tomcat instance.
UPDATE: One issue I have with putting those JARs in Tomcat's /lib directory is that now every app that you deploy to that instance sees those JARs - change them for one, all are affected. If you put the JARs in each individual WEB-INF/lib, you can modify each application without affecting others. The cost is duplicate JARs and disk space, which is cheap.
Another problem if you have to migrate from devl->test->prod, now every environment has to have the identical JARs deployed in order for your app to work. Miss one and you're broken. Your app depends on having those dependencies available. If they aren't on the server you're out of luck. Keep control in your own hands and package the JARs in the WAR file.
You need to be careful externalizing the dependencies like that in a web server environment. Depending on the server there can be unexpected class-loading issues even when it seems to start up fine.
I agree with duffymo... 19MB is not really all that big... is there some reasoning behind wanting to do this? I wouldn't recommend it.
find the webapp folder
upload the files direct into the folder
for example
/path-to-tomcat/webapp/myapp/
keep the /path-to-tomcat/webapp/myapp/WEB-INF/lib folder and upload the changes to ur /path-to-tomcat/webapp/myapp/classes folder
then use tomcat manager to restart the app
I second the suggestion of sending updates directly to ${CATALINA_HOME}/webapps/<your-app> on the target server. WARs are for production deployment, but if you have a slow connection and a large WAR that's no fun.
You'll want your web app to restart after the update, of course. Tomcat in development mode will monitor a few files for changes; by default WEB-INF/web.xml is one of them, so update that along with whatever else you're updating and you should get an app restart soon. In a pinch, you can use the Manager web app to kick the app awake.
For more control and convenience, you'd eventually do well to use the Tomcat ant tasks (found near the Tomcat distribution, not included with ant!) to restart the server, and perhaps to deploy your changes as well. Takes some fiddling but this is well worth it as you'll want to re-use it for each project you do.
Is WEB-INF/lib empty?
Where is log4j.jar?
Where is spring.jar?
This looks like classloader visibility problem.
Listen to duffymo and cjstehno.
Adding jars to tomcat's is a sure recipe for disaster.
Keep your jars in your webapps directory.
It is strange that Tomcat can't find the jar files. Anyway, place all jars in the common folder (${catalina.home}/lib). (This is even worse than using the shared.folder, but it should work for you).
Of course, like others said, you shouldn't do that in your production system. I believe that is OK for a development system though - especially if you need to do extensive testing with the production system anyway.
Another note: you should only do this if you have full control of the server and you are the only one installing applications.
Why would you change the default ${shared.loader} property of tomcat?

How to avoid copying 40M of java lib's within a WAR when the WAR's size is 41M?

At the moment my build process consists of repackaging the war file with all required java libraries under WEB-INF/lib and then copying the war file to development/demo/production server to be redeployed by tomcat.
The packaged war file's size is about 41M and it has at the moment something like 40M of external java libraries. There has to be a better way. How have you solved this issue?
My development machine is a windows box with Eclipse as my IDE and Ant as my build tool. The servers are all linux boxes with Tomcat 5.5.
Should I maybe add the jar files to the war package at server side?
I can see what you are saying, and have had the same frustration with some of our webapps, but for consistency sake, I would suggest you keep things as they are. If copying the libraries to the tomcat/lib directory you may run into issues with the system classpath vs. the webapp classpath.
By keeping things as they are you are sure you are deploying the same stuff in development/demo as you are in production. Life sucks when you are manually tweaking stuff in production, or you have some crazy error because you forgot to update XYZ.jar from version 1.6 to 1.6.1_b33 in production and now it's behaving differently than what you believe is the exact same code on demo.
When working with something vital enough to have dev/demo/production systems, I think consistency is much more of an issue than .war file size.
We use the rsync tool for this (in our case, using cygwin under windows) to copy the deployments to the servers (which run linux). We use exploded WAR/EAR files (i.e. a directory structure called MyApp.war rather than a zip file called MyApp.war), rsync will only transfer the files that have changed.
In general use, rsync will transfer our 30-40 megabyte exploded EARs in about 5 seconds.
Tomcat has a shared/lib directory, which is the proper place for global application dependencies. However, these will be visible to all applications, which will affect dependency management and may have consequences for things like static variables. I'm not sure if you can configure anything better in Tomcat.
An alternative is to switch to a more sophisticated web container. For example, WebSphere Application Server Community Edition (a blue-washed version of Geronimo) supports per-asset libraries. Other free and commercial servers support this, too. I know WebSphere Application Server does and I'm pretty sure you can do it in Glassfish.
#McDowell, when mentioning those J2EE servers, you should precise that they are J2EE servers(servlet container + the rest).
Like #digitaljoel, I suggest to keep things like they are. It looks like you haven't done much web application deployment yet. The issues that you'll have are not worth the price(version conflicts, deployment errors, etc.).
Can you add the non-changing Jars to the Java Library Path on the server side, and only include the regularly changing Jars in your WAR?
you could include the external java libraries in the Tomcat/lib directory. That way they stay on the server.
You could just deploy as a JAR file, replicate your deployment environment locally and just copy over the files that have changed and the jar itself. The pathing is the only real issue.
Or you could look into setting up an EAR.
I work with the 'exploded web application' in the development servers, and occasionally in production as well. The deployment process (based on ANT) updates the JARs in WEB-INF/lib with our packages. Only in the development server, we activate Tomcat reloading which takes care of restarting the application when something changes. You should assign some extra permanent memory to these Tomcats and have a way to restart the server, as the reloading may crash Tomcat from time to time.
I know it's a weird configuration, but I can't understand how constantly repackaging the 30MB (and growing) of our typical application could do any better. May one day the development descriptor allow for external references to libraries which the container may download and cache. ??
Excuse my poor English.
What you need is a version control tool and a build process.
Use CSV,SVN,GIT or whatever fit you to keep your source under control.
use a build tool to build your application : Maven,ant,...
Now, when you want to deploy your application on your server ,you just have to commit your updates on your computer,update your source on your server,build your application and deploy it from the server.
This way , the server will just have to load your modifications and it should be much faster.

Categories