Can/should I depend on WebLogic's bundled modules - java

My target platform is a WebLogic 12c application server.
I have an ear-project, which on startup requires e.g. org.apache.commons.logging.LogFactory.
I know that this class - an related classes - can be found in <WL_HOME>/modules/com.bea.core.apache.commons.logging.api_1.1.1.jar, but it is not by default available on the classspath.
In such cases - am I supposed to somehow make the jar file in <WL_HOME>/modulesavailable on the classpath - or should I provide whatever jar file I find suitable - either bundled in the application, or placed in <WL_HOME>/user_projects/domains/<mydomain>/lib?
If I am to use the one in the <WL_HOME>/modules folder - how do I configure my domain to make it available?
To me it seems reasonable that the jar files in the modules folder should be considered provided dependencies, but so far I have been unable to find the right way to enable them as such - I have been browsing for an answer for hours:-)
UPDATE:
I know I can simply add them to the CLASSPATH variable in the server startup script - my question is more like - should I? Is there a better way - or should I completely forget about <WL_HOME>/modules?

That's a short-sighted approach.
you need to reboot the server to upgrade libraries
every app on the server must be okay with those libraries in their claspath
Weblogic has the concept of Shared JEE Libraries (example). In short, you add extra lines to MANIFEST.MF and configure the jar differently, then you can reference it in other apps using weblogic-application.xml or whatever.
The point is that you can upgrade the library without restarting the server (provided you gave it a version like 1.1 (there were bugs last time I named it 1.1.1 - it needed to be able to cast it to a floating-point number to seamlessly upgrade)).
If you just want to include some libraries but not share them outside the app, then just specify the correct <prefer-application-packages> or < prefer-web-inf-classes> element, depending on whether you have an EAR or a WAR.

Related

JDBC driver not found (servlet, DAO, mariaDB) [duplicate]

I developer a web application using Java. When I deploy it to my application server (Jetty, Tomcat, JBoss, GlassFish, etc.) throws an error. I can see this error message in the stacktrace:
java.lang.ClassNotFoundException
Or
java.lang.NoClassDefFoundError
What does this mean and how can I fix it?
What does this mean?
First, let's see the meaning of java.lang.ClassNotFoundException:
Thrown when an application tries to load in a class through its string name using:
The forName method in class Class.
The findSystemClass method in class ClassLoader.
The loadClass method in class ClassLoader.
but no definition for the class with the specified name could be found.
Usually, this happens when trying to open a connection manually in this form:
String jdbcDriver = "...'; //name of your driver
Class.forName(jdbcDriver);
Or when you refer to a class that belongs to an external library and strangely this class cannot be loaded when the application server tries to deploy the application.
Let's see the meaning of java.lang.NoClassDefFoundError (emphasis mine):
Thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class (as part of a normal method call or as part of creating a new instance using the new expression) and no definition of the class could be found.
The searched-for class definition existed when the currently executing class was compiled, but the definition can no longer be found.
The last part says it all: the class existed at compile time i.e. when I compiled the application through my IDE, but it is not available at runtime i.e. when the application is deployed.
how can I fix it?
In Java web applications, all third party libraries used by your application must go in WEB-INF/lib folder. Make sure that all the necessary libraries (jars) are placed there. You can check this easily:
- <webapp folder>
- WEB-INF
- lib
+ jar1
+ jar2
+ ...
- META-INF
- <rest of your folders>
This problem usually arises for JDBC connectivity jars (MySQL, Derby, MSSQL, Oracle, etc.) or web MVC frameworks libraries like JSF or Spring MVC.
Take into account that some third party libraries rely on other third party libraries, so you have to add all of them in WEB-INF/lib in order to make the application work. A good example of this is RichFaces 4 libraries, where you have to download and add the external libraries manually.
Note for Maven users: you should not experience these problems unless you have set the libraries as provided, test or system. If set to provided, you're responsible to add the libraries somewhere in the classpath. You can find more info about the dependency scopes here: Introduction to the Dependency Mechanism
In case the library must be shared among several applications that will be deployed on your application server e.g. MySQL connector for two applications, there's another alternative. Instead of deploying two war files each with their own MySQL connector library, place this library in the common library folder of the server application, this will enable the library to be in the classpath of all the deployed applications.
This folder vary from application server.
Tomcat 7/8: <tomcat_home>/lib
JBoss 7/Wildfly: <jboss_home>/standalone/lib
The class must exist under WEB-INF/classes or be inside a .jar file under WEB-INF/lib. Make sure it does.
Same problem happen with me.
Might be possible one of your libraries are using some classes internal which is not available
in your lib or maven dependency pom.xml.
Thats means you have analyze your error logs and identify these classes and then import all dependencies in maven or lib folder.
I have fixed this error by the same way.
because some of my libraries are using activation.jar and json.jar internally.

What are servletcontainer specific libraries?

In posts like https://stackoverflow.com/a/4076706/5467214 or https://stackoverflow.com/a/8743562/5467214 I keep reading about "servletcontainer specific libraries", that shouldn't be included manually in JavaEE projects, if I understood it correctly. Libraries like servlet-api.jar, jsp-api.jar, el-api.jar, j2ee.jar or javaee.jar are mentioned, but normally followed by an "etc.".
Is there a good explanation what "servletcontainer specific" means or perhaps an exhaustive list of which libraries are servletcontainer specific for Catalina, for example? Or for other servletcontainers? For example, jstl-1.1.2.jar gets explicitely loaded via the pom.xml in a project I am working on that runs on a Tomcat7. Is this "servletcontainer specific library"?

Websphere: Shared libraries in common classloader earlier on classpath than application modules, even with parent last policy

Background:
I have the following problem: I have several WAR files I need to have deployed on same Websphere server. The WAR files use libraries that depend on having a specific version of XMLSec regisered as the XML Signature Provider (with the Java Security class). Currently I bundle this library with each WAR file (since the WAR files also need to work standalone and on Tomcat's without any special shared library configuration etc.). Each WAR files registers the provider with Security.addProvider() in a ServerContextListener. But this causes problems in the multi-WAR setup, because if one WAR file does the registration with Security.addProvider) and another WAR files tries to fetch it using the XMLSignatureFactory class (which is actually a javax.* class contained inside the XMLSec JAR itself, but which ultimately calls back to the global provider list configured with Security.addProvider), then it causes a ClassCastException inside XMLSignatureFactory, because this class does a cast of what it gets from Security into to its own version of the provider classes, which doesn't work. The exact stack trace is as follows:
Caused by: java.lang.ClassCastException:
org.apache.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory
incompatible with javax.xml.crypto.dsig.XMLSignatureFactory at
javax.xml.crypto.dsig.XMLSignatureFactory.findInstance(XMLSignatureFactory.java:202)
at
javax.xml.crypto.dsig.XMLSignatureFactory.getInstance(XMLSignatureFactory.java:292)
By the way this is not a case of conflict with different versions of XMLSec being in play or conflicts with Websphere's own version. There is only one version albeit it is loaded from different WAR's.
Of course the solution is to have the xmlsec library loaded with a common classloader so that there is only one version of the classes loaded that all WAR files see, which would avoid ClassCastExceptions etc.. But here is the rub: I also need to have each application loaded with the "parent last" policy - or rather, I need the JAR files inside each application to take precedence over Websphere's built-in version of the libraries (for instance Axis2 that I also include in the WAR filesetc.). Furter, I would prefer that I can keep the xmlsec library in each WAR files' WEB-INF/lib folder, so that the WAR files can still work stand-alone (i.e. in other environments which might not have the shared library configured etc.).
So basically I want to have a common class loader loading the XMLSec library, say, somewhere from disk. Let's denote that [SHARED XMLSEC]. Then I want each application classpath to ultimately appear like this:
App1: [SHARED XMLSEC][App1 WEB-inf/lib][Websphere libraries][JDK libraries]
App2: [SHARED XMLSEC][App2 WEB-inf/lib][Websphere libraries][JDK libraries]
etc.
In such a configuration it doesn't matter if App1+App2 themselves contain the XMLSec library since the shared one will take precedence so they will use the common one. At the same time, App1+App2 are still free to override other built-in Websphere libraries (Axis2).
Is it possible to realize this configuration and what options do I need to set? Do you see alternative ways to achieve the same objective?
Since you have a conflict between classes here, I would suggest going for isolated class loaders for each application. On the server side, setting the class loader policy to 'Multiple' should provide isolation between applications.
Once you have this set, configure class loading at the application level to the 'Parent last' configuration for both the applications.
The following Knowledge Center link has the relevant instructions [Steps 2,3 & 4 under the 'Procedure' section] :
http://www.ibm.com/support/knowledgecenter/en/SSAW57_8.5.5/com.ibm.websphere.nd.multiplatform.doc/ae/trun_classload.html
[Note: The version of WAS in use is not specified in the question. The Knowledge Center link refers to version 8.5.5.]

Hibernate and Jersey dependency conflict (javassist) - can anyone explain how this works?

I'm currently using hibernate-4.1.4 and jersey-2.22. These have javassist-3.15 and javassist-3.18 respectively.
I included both hibernate and jersey in my project and to my surprise, there were no dependency conflicts between the said javassists.
I was wondering how Java tells hibernate to use 3.15 and how it tell jersey to use 3.18 since both are in the build path. Is one javassist not being used?
Follow up question: Let's say that javassist-3.15 and javassist-3.18 have a conflict with each other. How do I resolve this? Do I disable both javassists and include one externally?
EDIT: My app is a web app that runs on Tomcat 7. We don't use Maven/Gradle. We just configure the dependencies by putting the jars in the build path using Eclipse.
JAVA loads classes through ClassLoaders ... Many applications servers, as Tomcat or Wildfly, implement and use their own class loaders (not the regular ones of the common JDK) ... So you must check the Tomcat documentation to read about its classloading behaviour...
After saying that, is very likely that Tomcat is loading libraries in alphabetical order. I Explain...
Suppose that you use a class named: Dummy, and this class is contained at the libraries: dummy-1.0.jar and dummy-1.1.jar ... when the class Dummy is requested, the Tomcat ClassLoader search for that class definition, looking first at dummy-1.0.jar and later at dummy-1.1.jar ... given that dummy-1.0.jar contains that class, Tomcat stops looking a returns that class version ... If dummy-1.0.jar would not have the target class, the dummy-1.1.jar class version would be returned instead...
(I suggest to try this to validate the container behaivour, it's not so hard to implement)...
And yes, if javassist-3.15 and javassist-3.18 conflicts with each other, you should remove them and pick the javassist JAR more
suitable for both libraries (jersey and hibernate).
As thumb rule, I tend to pick the newest library (the one with greater version), but this scheme not always work...

Need in understanding classpath in resource location and variable value set

Although I have been working in java for a while, there are many small things I have been ignoring, which at times have become bottleneck in productivity. I have difficulty in understanding this:
This is one of the bean.xml which gets placed in the final .war file (in a web application, built with spring framework).
<context:property-placeholder
location="classpath:/${deploy.env}/com.example.config/db.properties"
ignore-resource-not-found="false" />
I have following doubts:
1) At the time of building the code, i did like this for passing value of deploy.env
mvn clean install -Ddeploy.env=local
I ran the mvn in debug mode and could see this set to local. Now, the thing is, in the .war that gets generated, it is still ${deploy.env} (see above snippet). Doesn't this get replaced in the final .war? If not, then how do we pass the value which we intend to set?
2) what does "classpath:/${deploy.env}/com.example.config/db.properties" mean? Who sets the value of classpath? Are classpath capable of providing the location of resource files as well?
Assuming deploy.set --> local, so would this get translated to:
classpath:"/local/com.example.config/db.properties"
So does this mean db.properties would be present at: /local/com.example.config/db.properties
Any inputs to understand this would be of great help.
deploy.env is either environment variable or system property available to the JVM at run time.
The classpath:/${deploy.env}/com.example.config/db.properties will be resolved at run when your war is running in the container.
Set deploy.env=whatever in the shell from where you starting the tomcat or set in the environment of the user which starts the tomcat.
mvn clean install -Ddeploy.env=local here the deploy.env system property is available at build time. This will not replace the value of your spring config.
classpath is where all your classes and libraries bundled in the war are available along with the tomcat libraries. The spring property configurer will look for the db.properties file in the classpath at location e.g. /local/com.example.config
Spring documentation to learn more
Some explanation on my blog post
As stated in the Oracle Web site: The CLASSPATH variable is one way to tell applications, including the JDK tools, where to look for user classes.
That classpath: is referring to that location in particular, whatever it is, so it will start looking for those resources defined by Spring from that location and on, until it finds the first match.
Also, if you have that as a property in Maven, the value can be replaced with the right plug-in and configuration; not quite useful when you want a build that can be used with many values within those .properties files for different environments.
You can use other prefixes as file:, http:, etcetera. But you are just wondering about classpath:.

Categories