I have a Maven project that is distributed commercially that offers the ability to connect to many different databases via JDBC. Normally the customers place the necessary JDBC drivers in their web server's lib directory to make them accessible. We can't include certain jdbc drivers in the pom, for example Oracle, due to it's license type.
I'm trying to use an Oracle JDBC connection in the app while running in Eclipse. I need to get the JDBC jar on the class path and for some reason can't seem to be able to do that without adding it to the pom.xml via maven dependency.
I thought for sure going to Properties-->Java Build Path --> Libraries --> Add External JARs would work. When added to the build path in that way it shows correctly in the package explorer but if I run Class.forName at run time it throws ClassNotFoundException. Why isn't it on the class path at that point?
Take a look at the following descriptive article, which gives the shortcuts to setting a classpath to your throw-away code or to have a modest solution to manage your classpath dependencies and then to a complete and a professional solution to manage and even automate your classpath dependencies - should there be a need to have these automated for a larger projects.
It is a better way to set your CLASSPATH variable if you are not going to change any of those jar versions very frequently or else you might end up hours of your valuable time debugging the wrong side of the problem.
Hope this helps you understand and also resolve your problem!
I would include the relevant jars into the pom, but make them <optional>. Then, they are not packaged into the application but they can be provided by the user.
Related
For my development station, I need my project to "see" the JDBC drivers. But when I deploy the project to the server, if the JDBC drivers are in the /lib folder they'll cause the container to misbehave.
I tried setting the <scope>provided</scope> to the drivers I don't want to package on my .war file, but I can't get my IDE to run the project.
What's a correct scope to declare the JDBC drivers on pom.xml so they don't get packaged for deploy and I can work with them on my development station? <scope>runtime</scope>?
Thanks in advance,
The short answer for your question is: you should use provided scope.
Why not runtime? Let's check Maven docs:
provided
This is much like compile, but indicates you expect the JDK or a container to provide the dependency at runtime. For example, when building a web application for the Java Enterprise Edition, you would set the dependency on the Servlet API and related Java EE APIs to scope provided because the web container provides those classes. This scope is only available on the compilation and test classpath, and is not transitive.
runtime
This scope indicates that the dependency is not required for compilation, but is for execution. It is in the runtime and test classpaths, but not the compile classpath.
So, Maven may not expose runtime scoped dependencies in compile's classpath, thus you won't be able to use them in you code directly. However, the code like Class.forName("class.from.runtime.Scope") will compile ok.
I guess the problem is your IDE which didn't seized pom.xml changes. Usually, this problem is fixed by "cleaning cache" or "updating" / "syncing" your project. Here is how to do this in Eclipse and IDEA.
I have inherited an old project that using ant to build against weblogic.jar. I am moving this into a more modern maven based build environment and I don't want to check in weblogic.jar ( which is 34MB ) into my private artifact repository and I don't want to add it to my local repository either. I am not sure what it is using from this, the project is one monolithic code base over 500,000 lines of code.
We won't actually have Weblogic on our local development machines, we are deploying to remote virtual machines to test because of corporate network topology to get the services our application needs to talk to.
What alternative do I have to building against weblogic.jar.
Using system scope is usually considered a bad practice. However, I would say in the case of weblogic.jar, using system scope makes sense. The reason is that the the weblogic.jar does not contains all the classes provided by WLS installation. If you open weblogic.jar and take a look at the MANIFEST.MF file inside, it contains a long list of jar files in the Class-Path: entry. These jar references are all using relative path. It means that if you put the weblogic.jar into the maven repository, the relative path is broken and you need to a lot more WLS jar files into your maven repository.
The catch is that if your system-scoped dependency points to the weblogic.jar in your WLS installation, you need to standardize the WLS installation directory for all your developers. Otherwise your build is not portable in other developers' machine.
Since maven downloads everything it tries to resolve into your local repository the only way (afaik) would be wrapping the existing ant task using maven-ant-task.
Personally I would prefer to add the weblogic stuff into the maven repository.
If you don't want to put it into your local repo, you could refer to it using system-scoped dependency, in which case you'd just refer to it from your disk. I'm not sure why that would be better option, but since you asked for it, you might have a solid reason.
However assuming you don't want to use weblogic.jar at all: it's not really possible to say what alternatives to building against it you have without knowing what you need from it. That needs to be found out first. If you use weblogic-specific stuff, you do need the reference.
JBoss has the jbossall-client.jar which can be used in client applications for JNDI lookups and more... It is available in the JBoss maven repository.
How should one do it when using Glassfish 3 in a dependency managed environment?
The FAQ says in step 3 that one should refer directly to gf-client.jar in the installation directoy of glassfish. The gf-client.jar only has relative references to other JARs in glassfish installation directory. So putting the gf-client.jar in a private repository is no option, unless you are willing to put alls the refered JARSs into the repository, too. But that is no good, because then you have to put the manually to the correct relative location.
There is a package-appclient script which generates a appclient.jar, which is not directly usable in a classpath, because it mainly just a ZIP-file containing all needed JARs for a client. Of course you could put appclient.jar in the repository and then do all the extraction and classpath-building in a build script, but should I really do it this way?
Is there any other way to do it, or better how it is intended to use this appclient.jar?
Have I overseen a "glassfishall-client.jar"?
I'm not familiar with your exact problem but I can speak on one of your statements:
So putting the gf-client.jar in a
private repository is no option,
unless you are willing to put alls the
refered JARSs into the repository,
too. But that is no good, because then
you have to put the manually to the
correct relative location.
I manage our local repository and I can tell you, it's very easy to include "alls the refered JARSs into the repository." To do so, you run the install task with transitive set to true. That looks like this:
<ivy:install organisation="[orgName]" module="[modName]" revision="[rev]"
from="myRepositoryChain" to="myLocalResolver" transitive="true" />
It's hard to tell from your question but I'm guessing the problem is that some of those dependencies are only available directly from JBoss? As long as you include the appropriate repository in your "myRepositoryChain," it all will work, effortlessly.
If these jars are hard to access, then that's all the more reason to pull them into your local repository, somewhere.
I hope that helps, in some way.
Here's a great resource for more info on managing a local ivy repository.
Quite new to maven here so let me explain first what I am trying to do:
We have certain JAR files which will not be added to the repo. This is because they are specific to Oracle ADF and are already placed on our application server. There is only 1 version to be used for all apps at anyone time. In order to compile though, we need to have these on the class path. There are a LOT of these JARS, so if we were to upgrade to a newer version of ADF, we would have to go into every application and redefine some pretty redundant dependencies. So again, my goal is to just add these JARs to the classpath, since we will control what version is actually used elsewhere.
So basically, I want to just add every JAR in a given network directory (of which devs do not have permission to modify) to maven's classpath for when it compiles. And without putting any of these JAR files in a repository. And of course, these JARs are not to be packaged into any EAR/WAR.
edit:
Amongst other reasons why I do not want to add these to the corporate repo is that:
These JARs are not used by anything else. There are a lot of them, uncommon and exclusive to Oracle.
There will only be one version of a given JAR used at anyone time. There will never be the case where Application A depends on 1.0 and Application B depends on 1.1. Both App A and B will depend on either 1.1 or 1.2 solely.
We are planning to maintain 100+ applications. That is a lot of pom.xml files, meaning anytime we upgrade Oracle ADF, if any dependency wasn't correctly specified (via human error) we will have to fix each mistake every time we edit those 100+ pom.xml files for an upgrade.
I see three options:
Put the dependencies in a repository (could be a file repository as described in this answer) and declare them with a scope provided.
Use the dirty system scope trick (i.e. declare the dependencies with a system scope and set the path to the jars in your file system.
Little variation of #2: create a jar with a MANIFEST.MF referencing all the jars (using a relative path) and declare a dependency on this almost empty jar with a system scope.
The clean way is option #1 but others would work too in your case. Option #3 seems be the closest to what you're looking for.
Update: To clarify option #3
Let's say you have a directory with a.jar and b.jar. Create a c.jar with a Class-Path entry in its META-INF/MANIFEST.MF listing other jars, something like this:
Class-Path: ./a.jar ./b.jar
Then declare a dependency in your POM on c (and only on c) with a system scope, other jars will become "visible" without having to explicitly list them in your POM (sure, you need to declare them in the manifest but this can be very easily scripted).
Although you explicitly stated you don't want them in the repository, your reasons are not justified. Here's my suggestion:
install these jars in your repostory
add them as maven dependencies, with <scope>provided</scope>. This means that they are provided by your runtime (the application server) and will not be included in your artifacts (war/ear)
Check this similar question
It is advisable that an organization that's using maven extensively has its own repository. You can see Nexus. Then you can install these jars in your repository and all developers will use them, rather than having the jars in each local repository only.
(The "ugliest" option would be not to use maven at all, put put the jars on a relative location and add them to the classpath of the project, submitting the classpath properties file (depending on the IDE))
if you are developing ADF (10g / 11g I guess) components, I suppose you'll be using JDeveloper as IDE. JDeveloper comes with a very rich Library Management Tool that allows you to define which libaries are required for compiling or which ones should be packaged for deployment. I I suppose you will already know how to add libraries to projects and indicate in the deployment profile which ones should be picked while packaging. If you want to keep your libraries out of maven, maybe this could be the best approach. Let´s say the libraries you refer too are the "Webcenter" ones, using this approach will guarantee you you have the adequate libraries as JDeveloper will come with the right version libraries.
Nevertheless, as you are using maven I would not recommend to keep some libraries out of control and maven repositories. I´d recommend choose between maven and Oracle JDeveloper library management. In our current project we are working with JDeveloper ADF 11g (and WebCenter) and we use maven, it simply make us library management easier. At the end of the day, we will have a big amount of third party libraries (say Apache, Spring, etc.) that are useful to be managed by maven and not so many Oracle libraries really required for compiling in the IDE (as you would only need the API ones and not their implementations). Our approach has been to add the Oracle libraries to our maven repository whenever they are required and let maven to control the whole dependency management.
As others say in their answers if you don´t want the dependencies to be included in any of your artifacts use <scope>provided</scope>. Once you configure your development environment you will be grateful maven does the work and you can (almost) forget about dependency management. To build the JDeveloper IDE files we are using the maven jdev plugin, so mvn jdev:jdev would build generate our project files and set up dependencies on libraries and among them to compile properly.
Updated:
Of course, you need to refer to ADF libraries in your pom files. In our project we just refer to the ones used on each application, say ADF Tag Libraries or a specific service, not the whole ADF/WebCenter stack. For this purpose use the "provided" scope. You can still let JDeveloper to manage your libraries, but we have found that it's simpler to either have a 100% JDeveloper libraries approach or a 100% maven approach. If you go with the maven approach it will take you some time to build your local repo at first, but once that's done it's very easy to maintain, and the whole cycle (development, build, test, packaging and deployment) will be simpler, having a more consistent configuration. It's true that in a future you'll have to update to later ADF versions, but as your repository structure will already be defined it should be something fast. For future upgrades I'd recommend to keep the ADF version as a property on the top pom, that will allow you to switch faster to a new version.
Perhaps the reason I stalled learning Java until now is because I HATE how Java handles external libraries. I'm stuck keeping them in one place, adding them individually, fixing problems with versioning and every time I move/rename them, and copying and writing the classpath over and over each time I release a Java application.
There has to be an elegant solution to all of this. I keep all of my libraries (regardless of task, platform, or other) in their own little folder inside a "lib" folder in my development folder, kind of like this:
Dev
-lib
+JS-jQuery
+Flex-Degrafa
-Java-Xerces
+Xerces-1.2.3
+More libraries
I can use either Netbeans or Eclipse for Java dev, but none of them provide a very streamlined (and not to mention idiot-proof) way of managing all of these.
A nudge in the right direction or an online article/tutorial on this would be greatly appreciated.
You can either use Ant + Ivy or Maven to manage your library dependencies.
If it is only dependency management you're after and you're happy with the rest of your build process, I would use Ivy, as it can unobtrusively manage your dependencies, leaving your existing build process intact. There is a plugin for Eclipse called IvyIDE that contributes your dependencies via a classpath container.
Maven 2 has a steeper learning curve but provides a much richer set of functionality for building your projects and Eclipse integration through m2eclipse or IAM.
Personally I use Maven as I have a large number of projects to work with and Maven is particularly suited to efficient development across lots of projects.
Have a look at the introductory documentation to see what works for you.
Ivy Tutorial
Maven Getting Started Guide
Netbeans 6.7.1's Maven support is quite good and comes out of the box with the IDE.
The Eclipse addon was frustrating enough that I gave Netbeans another try.
A third choice besides ChssPly76's options is to use Ant with the Maven Ant Tasks. I don't know if I'd call any of these solutions particularly "elegant," but they do spare you the need to manage your own lib/ directory and classpath variables.
If you're working on Linux you can install Java libraries with APT or RPM.
Otherwise, I normally check precompiled JARs into a lib directory in my project's version control repository and make sure the names of the JAR files include full version information. E.g. lib/foo-1.5.6.jar, not lib/foo.jar.
To avoid having to manually set the classpath before running your app, you can set the classpath in the Manifests of the JARs themselves to define the dependencies of each JAR file. The JVM will follow all the dependencies when loading classes.
Maven is often more trouble than it's worth, but the ability to open a maven project directly into IDEs such as IntelliJ is excellent. For example, IntelliJ will download all dependencies and have them available without having to run a build first, or an mvn command and then a project refresh. It also isn't necessary to re-generate the project every time a dependency is added. I work with a number of Eclipse developers who switched to IntelliJ for this alone.
However, one shortfall of Maven is that many libraries (or versions of libraries) are not available on public repositories. Therefore it is often necessary to set up a local repository such as archiva. In ant, it would just be a matter of adding it to the lib directory in the repository.
Maven can also attack when you need to do something that maven doesn't directly support via a plugin. What would normally be a few lines of ant can often turn into a morning's worth of work.
Finally, buildr is an excellent way of using Maven's dependency management and plugins, while also supporting ad-hoc tasks.