We are trying to deploy a web service (a .war file) onto an Oracle WebLogic 12.2.1.0.0 Server.
The .war contains some third party .jars, for example log4j-api-2.12.0.jar, that are multiple release .jars (per JEP 238, having Multi-Release: true in MANIFEST.MF).
As such, it includes some Java 9 compiled classes in the META-INF/versions/9 directory. WebLogic 12.2 uses Java 8 only (confirmed version as Java 1.8.0_92 via WebLogic Admin Console).
As I understand it, Java 8 servers are supposed to not see / ignore any classes under the META-INF/versions directory, but this does not seem to be happening. It appears as though Oracle WLS is just scanning the whole .war.
As a result, when we try to deploy the .war, we get errors like this one:
BEA-160248 Unable to parse class file:... (then a long path name into the META-INF/versions/9 directory)
Is there something special we need to do to make this work? I'll accept anything along the lines of:
Configure WLS somehow to ignore the META-INF/versions/9 classes
Configure Maven to somehow build the .war without the META-INF/versions/9 classes that are present in the third-party .jars.
I'm not interested in answers involving manually deleting anything from the .war every time it is built. Also, I'm not sure I can downgrade to earlier versions of the 3rd party .jars at this point. Log4j2, probably could... but there are others.
Thanks!
JEP 238 is from Java 9 and WebLogic Server does not run with Java 9.
After looking into it further, the
BEA-160248 Unable to parse class file...
messages were a red herring. After solving other, unrelated problems, the application does deploy and work as needed, in spite of these error messages appearing in the log.
I would like to add that according to Doc ID 2629550.1:
This message is harmless and can be ignored.
Related
I would like to know if there is a standarized procedure to deploy an EAR component into WebLogic 11 server.
I'm having some issues with a deployment that doesn't looks like it's working propertly.
Server specs
Oracle Linux server
Dump from "cat etc/os-release"
ORACLE_BUGZILLA_PRODUCT="Oracle Linux 6"
ORACLE_BUGZILLA_PRODUCT_VERSION=6.8
ORACLE_SUPPORT_PRODUCT="Oracle Linux"
ORACLE_SUPPORT_PRODUCT_VERSION=6.8
Weblogic 11 (10.3.6.0)
Java 1.6
Before I'm going to deploy the EAR I do the following steps:
Stop weblogic server.
Delete cache, tmp and logs folders and his content.
Backup the old EAR.
Transfer via SFTP the new EAR.
I don't know if I'm missing something to make sure everything is in order.
Do you have any idea of what could I be missing?
I have been searching but I couldn't find any clue.
I think your list sounds okay, except for deleting the logs. I'd prefer that you back up the logs than preserve the old EAR.
It should be possible to rebuild an EAR from the labeled branch/version in the code repository. Backing up the EAR should only be done until the new deployment is up and running. Once it's alive I'd delete the old EAR.
I'd recommend automating all of this. If you're doing it by hand, it's time to follow the crowd.
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.
I created a client using proxy in Oracle JDeveloper to call web service. JDeveloper deployed automatically and the code works well under windows environment. But now I'm required to migrate the code to unix server. I deployed the project to a .war file and copy it to unix which cannot be executed correctly using "jar" command.
Could anybody give me a whole picture or a high-level step-by-step instruction about what I need to set up to execute war on unix? I'm new to this area, and for now I got some suggestions like installing a Tomcat first.
What I have now:
1. a war file including .class, .java, WEB-INF, META-INF, MANIFEST.MF deployed from JDeveloper
2. JDK 1.6.0_25 installed on unix usr/java/
3. Tomcat installed on unix, but not under bin or local or usr directory(is it ok?)
Some specific questions:
1. what else do I need?
2. where to drop the .war?
3. do I need to unzip or re-compile the war?
4. how can I run the main class in the war?
Errors poped-up now:
1. cannot find main class
2. I tried to un-zip war and compile the class including main, and get "cannot find symbol" for the webservice specified classes' name.
Thanks to whoever attempt to help!
Even though this question probably should've been asked on ServerFault instead of here, sounds like you got all you need. Try dropping the .war on tomcat's webapps directory.
You should be able to just drop the .war file in $CATALINA_BASE/webapps and tomcat should pick it up when you start it.
$CATALINA_BASE is where you installed tomcat, unless you've configured tomcat for multiple bases.
You only need a war file if you are developing web application. From what you describe, you need to create a zip file which contains all the libraries and classes you need and copy it to Unix. Then you unpack it and execute it using java command.
Alternatively you can create a jar file with all dependencies included using Maven Shade Plugin and execute your code using jar command.
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?
im switching jboss 4.2.2 to 5.0.1 and i have installed jboss. now on client side i replaced existing jar files. jbossall-client.jar,jboss-client.jar,commons-logging.jar,jboss-serialization.jar,jnp-client.jar. but still error came on logging.
java.lang.NoClassDefFoundError:
org/jboss/logging/Logger at
org.jnp.interfaces.NamingContext.(NamingContext.java:160)
could anyone shed some light.
note:(when i copy all 90 jars from jboss-5.0.1.GA\client into my client lib, my APPLICATION WORKING. but i don know what are the remaining jars exactly needed.) :(
The org.jboss.logging API classes are in jboss-logging-spi.jar. You'll probably also need either jboss-logging-jdk.jar or jboss-logging-log4j.jar.
In JBoss 4, the jbossall-client.jar contained a copy of every class that client applications might need. As of v5, though, it contains only a manifest file that refers to the other JARs, and so simply including jbossall-client.jar is no longer enough, you need to include the others as well.