Java Lib file errors - java

I am a brand new Java developer (I have been working in asp.net) and I inherited a project I am trying to get running correctly. I am on Windows 7 and have Tomcat installed and I am using Eclipse
I'm trying to figure out how the heck Jar's work in java and I am really confused at the moment. I have been playing around with it and looking up stuff on the web for about a day now and this is where I am:
I have a dynamic web project which I inherited and it has what I am going to assume is a fairly standard project layout. There is a lib folder in the project root which contains some jar's.
If I don't do anything and go to a particular page in the site I get this error: "The import net.sf cannot be resolved, XLSTransformer cannot be resolved to a type"
So I added jxls-core-0.9.8.jar to my build path in Eclipse and that error went away but now I am getting this error "java.lang.ClassNotFoundException: net.sf.jxls.transformer.XLSTransformer"
I copied that jar from its current location to the tomcat/lib directory and that error went away. Now I am getting essentially the same issue with another file.
Mainly I just need to know how should jar's work? Do they need to be in the class path, in web/WEB-INF/lib, in tomcat/lib, in all of them, none of them I just can't figure it out.
Also when I was looking around I saw some stuff that indicated the order of my classpath entries matters as well. If that is the case how do you insure you have them in the correct order.

Where your jars need to go actually depends - there are entire best practices and major headaches involved. The term Jar Hell exists for a reason.
All classes used by your application must be on the classpath. How they get there will vary depending on the classloader.
For a fuller understanding, you'll want to do reading on the Java classloader. Ideally you'll want to look into Tomcat's classloader, or at least a Servlet Container's classloader, as the classloader for Tomcat will differ from that for a Java SE (desktop) app, will differ from that for an applet. On top of that, classloaders can really bite you if you don't understand them. If you want the gory details of how a servlet container ought to work, you can check out the latest and greatest Servlet specification.
The information on Tomcat's classloader provides a best practice list for you. Note that I've linked a 5.5 version. If you are using a later or earlier version, check around for the same file for your version.

Here's a suggestion that might help in troubleshooting the problem.
WAR files (Web Archives) will put all of your application's dependency JARs in the directory WEB-INF/lib. If you get a report of a missing class, try unzipping your WAR file, or looking in the exploded webapp directory of your app server, and see if the necessary jar is there.
The difference between this location and tomcat/lib is that JARs in tomcat/lib are made available in Tomcat's parent classloader for all loaded apps. (Indeed this can cause a problem if an app has its own version of a particular JAR in WEB-INF/lib.) The JARs in WEB-INF/lib are loaded in the application's classloader and are only available to that app.
If your JAR is missing from WEB-INF/lib, check your build scripts or the Build Path of your project in Eclipse. Good luck!

In Eclipse, I export as "Runnable JAR file", and in the dialog after, under "Library handling", I choose "Extract required libraries into generated Jar".
Basically, what this means is that if I can run it in Eclipse without error, it will run stand alone too since everything that I've told Eclipse is required will be included in the JAR.

Related

JavaEE compiling files

I feel like a 4-year old who has a slice of bread with pb and a slice with jelly and is asking how to make a sandwich..
I've been given the responsibility of maintaining a javaEE website that was done by our parent company that no loner supports us. I'm relatively new to JavaEE and I'm trying to figure out how to recompile the files that need to be modified from within the root folder of the site.
I downloaded NetBeans to help me with this, but still can't figure it out. My problem is that the java files can't find any of the packages and resources they are dependent on. As far as I know, the resources are there.. although, I do see some packages starting with "com." and "javax.", and I don't see a 'com' or 'javax' folder anywhere.. I believe my problem has something to do with setting the class path in the project properties in NetBeans.. I tried that but either I'm not doing it right, or its not working. This whole Java compilation is so foreign to me, it'd be really great if someone could lead me in the right direction of getting this website compiled.
I posted a pick of the folder hierarchy of the website to help:
I'm trying to compile the RecordAdd.java file here specifically at the moment. Some of the packages it is trying to import come from its parent folder, asp, of the folder it is in, easp. The file is also trying to import com.icesoft.faces.component.*; where '*' consists of several different imports of the parent packages. I don't see a com folder like I mentioned, but I do see icefaces.jar files in the lib folder in WEB-INF folder. I've tried putting these folders in NetBeans Library-Compile category classpath, but that didn't do anything.
I'm not doing something right, that is probably a basic knowledge of compiling java projects, but I'm just not getting it. I really appreciate any help, just please don't be too harsh. Thanks!
Try to find out which IDE the original devs used. I see a nbproject folder which indicated Netbeans (unless that was created by you) so try opening the project in Netbeans as a Java EE project. I'd also try to open it in Eclipse, it has good importing capabilities and can sometimes figure out the classpath on it's own. Download the Java EE version of Eclipse and install the Web Tools Project. You can also try to see if there is a build file that will compile and generate a war file for you (something like build.xml).
It should be simple if the project was created in netbeans. Just go to File -> Open Project. Navigate to where the project is located. You will know if the folder is a project, because netbeans recognizes it and a different icon is displayed instead of a regular folder icon. Once you open your project, you can right click compile the project.
You don't use java compiler yourself to compile java files in a project. Compiling and building are done by tools like ant, maven... It's automated.
Importing existing projects into netbeans is a great way to loose a half a day.
I'm assuming that since there's a nbproject directory, this was built through netbeans, which should give you a leg up.
In the "Open Project" wizard, the top level of your application (not necessarily the sources) should have a friendly globe icon for a web application (.war) or a triangle for EE application (.ear). Open the triangle if there is one. Web applications can be packaged with EE applications through netbeans, so if the Web App you're trying to compile belongs to one, some of the build properties may be associated with it.
Looking at the file nbproject/build-impl.xml should give you hints about where your libraries folder was located. Make sure this path matches in your project properties under the Libraries header. These libraries can be shared among projects and therefore likely out of this projects directory structure and referenced or native to this project alone in which case jars are copied in to your lib folder.
There may be additional reference or server issues that netbeans detects (and gives a paltry error message for) which can be found in the project context menu under "Resolve Reference Issues" or "Resolve Missing Server". In netbeans projects are built against the servers they're run on right in the IDE. Check that you have the servers you want configured under Tools-> Servers, then ensure that server is linked in your project properties under Run.
This may not solve all your problems, but is a good start. Good Luck!

Best practice for creating a desktop app using Java WebStart

Hope I can explain this clearly. I am creating a desktop application that has dependencies on other external jar files. For example, my application is Spring-based so there are some SpringFramework jar files that I will need in my application.
I am using Java WebStart to 'launch' this desktop application. (As to why I am doing this is that I need to execute this customised desktop application via the website that we are building).
However I ran into troubles when I executing my desktop application by clicking on the jnlp description file. It gives errors stating that there is no class definition for some of the classes that my desktop application is using. I then realise that my desktop application when packaged as a JAR file, it didnt include my other JAR dependencies with it. Hence the reason for the error.
I guess, I could include the external JAR dependencies in my desktop JAR file but this would make my desktop JAR file quite large. And this will be then make the download of my JAR file slow due to the large JAR file since clicking on the JNLP descriptor file will always source from the desktop JAR file from the server. (unless I can 'tell' the JNLP descriptor not to download if there is no new version on the server.)
Anyway, I was thinking if this is an acceptable approach where my desktop JAR file will not include the JAR dependencies but only references to it. When my desktop application launches, it will check if these dependencies are available on the desktop, and if it is not available, it will call another JNLP descriptor that will download the external JAR files and copy them to a pre-determined location that my desktop application references. Will this work? or is there a simpler solution to my problem?
thanks
The JNLP file should include references to both your main file but also all needed libraries. This is standard functionality and you should do it that way.
Note that you should have a time stamp in your file names to avoid cache problems when updating code.
You need to have your JNLP reference the additional jars you have. Yes this will take slightly longer to download, but as long as you are not including a bunch of jars that you don't need this should not take very long. Web Start is smart enough to not re-download jars that have not changed on subsequent start ups of the same application. I have Java Web Start applications that have several large jars and this works just fine.
As far as putting the extra jars on the user's machine, I would not advise this. If you are going to do that, then there is not much of a point to use Web Start and you might as well install the entire program on the desktop.
The other answers covered most bases, but just thought I should add that it might make sense to mark the extra Jars as download='lazy'.

Unwanted jar files in tomcat/lib or WEB-INF/lib

I am currently working on an application which is around a decade old. When I looked in to the jar files which are associated with the application , I can see lots of jars which are not required and lots of different versions of same jar.
What are the cons of having unwanted jars in lib. What is the easy way to find and remove them?
You might get problems if a class loader decides to load classes from different version of jar file than you expect. These kind of problems are usually hard to track. Server will look through jars in some specific order (alphabetically by filename?) and use the first matching class/resource it finds. There are probably no guaranties that the newest version of a jar file is looked first.
I do not know of any tools that would find out which jars are unused. That may be impossible in general case due to reflection, but some degree of automatic checking should be possible, at least in theory.
Removing unused jar file by trial and error is problematic if you do not have good unit tests, which I doubt you have in your decades old application. There may always be some rare error case that depends on just the old jar version you just removed.
My suggestion is that if your applications are working, leave the jars as they are now. It will be very troublesome if not impossible to find out, which jar files are actually picked up by the class loader. (Of course do not deploy new applications).
You can find which packages a jar file contains by using JarAnalyzer. This will give you an idea of duplicates and you can start removing older versions of jar files. However this procedure needs to be done by hand and by trial and error. Also, the same package may be contained in two jars with different names and no versioning information.
As already said having different versions of the same jar could bring havoc. You can't know which version will actually be used and what conflicts it will bring to this or another application. That's why you should never use Tomcat's shared folder for applications jars. If you are in a situation, where many jar files are placed in the shared folder, avoid using this server for new applications.
By unwanted jar files in your application, do you mean that these are generated as part of your compile and build process every time? If so, then it might be the build scripts that you want to clean up.
If you are referring to the actual deployment environment, then any cleanup must be done very carefully. Why not try starting over in a fresh test environment with a clean tomcat installation and the latest build's executables deployed? See if it runs well on just that, and if it does, then maybe the extra jars are indeed unnecessary.
As for the cons, I don't see any aside from the filesize of your deployment.
How can you decide which of the jars are not being actually used?
I would suggest making this a full QA-needing change. You have no idea if the code chosen from the set of jars shadow an erroneous implementation surfacing if you remove an "obsolete" jar.

CLASSPATH, Java Buld Path (eclipse), and WEB-INF\LIB : what to use, when, and why?

I recently switched to J2EE from .NET, and am confused about where to put JAR files. I know that the CLASSPATH, WEB-INF, and Eclipse's Java Web Path are all places where JARs can be stored, but I'm confused about which folder to use, when, and why.
First off, we have the CLASSPATH. I usually set this by going into "Environment Variables" inside "My Computer." I know that this is the default place where the Java compiler looks for JAR files. When I add a folder or a JAR to my CLASSPATH environment variable, why is it ignored by Eclipse, the Java compiler, and the web server?
Also, I know that WEB-INF\LIB is a place where you can put JAR files that your web app is going to use. However, I've put JARs in WEB-INF\LIB only to have them be ignored. In what situations should I put JARs into WEB-INF\LIB folder? How do I get Eclipse or the web server to notice them?
So far, the only thing that works for me is to actually change the Java Build Path for an Eclipse project. I'll select the JARs I need and hit "Add External JARs." Most of the time when I do this, Eclipse will recognize my JARs and read the classes therein. However, I've run into a bunch of weird random errors while doing this (mostly having to do with dependencies, I think). For some reason, I just get the feeling that this isn't the right way to do things, and that I'm missing some vital piece of information. When should I be manually Adding External JARs inside Eclipse, and when should I be doing things differently? How come Eclipse's Java Build Path doesn't seem to know about the folders in my CLASSPATH environment variable?
Really, I would just like to gain a better understanding of the CLASSPATH, Eclipse's Java Build Path, and the WEB-INF/LIB folder -- the purposes they serve, the relationships between them, and where I should be putting my JARs in various situations. I would appreciate any advice you could give me, or any articles that you could recommend.
Thank you.
The CLASSPATH you set in your environment affects only standalone Java applications, i.e. ones you run from a command prompt or an icon. As you've noticed, Eclipse ignores this. It sets up its own per-project classpaths.
javac and java, if called from the command prompt, should/may honor this path, but it's no longer considered great practice to do this. It's turned out that every app needs its own set of stuff, so a global CLASSPATH isn't really doing any of them any good. Modern practice is to simply specify the classpath with the -cp option on the command line for javac or java.
A standalone Web Application server will also set up its own classpath. From the command line or GUI, WebAppServers are usually started by a script (.BAT or .sh) that sets up a classpath using -cp. Tomcat has a directory called common or common/lib where it expects to see libraries that should be available the the server and all programs running under it. But you will generally not need/want to mess with this, as it's customaries for applications to provide their own library collectons in WEB-INF/lib.
So for a Web app, you'd put your varous jars into the lib directory, under WEB-INF, assuming Eclipse pre-builds such a directory structure for you.
All the libs you need also need to be made known to Eclipse. In the Project Explorer, I select the whole slew of them at once, right-click and select Build Path | add to build path. That's easier than messing with Eclipse's project build path manually.
Java has a long history and experience has shown that some ideas were good and some were bad.
The CLASSPATH environment variable was the initial way to tell the Java machine where to locate classes from your program, and works reasonably well for command line programs. It was rapidly found that this should not be a global thing (as that tend to mess things up in the long run) but a per-program thing. This could be done by creating a wrapper script/BAT-file which sets the variable and runs the Java machine.
All was well, then people wanted to write web server stuff in Java. The Servlet API was created where a web application is a stand-alone unit - this resulted in that the CLASSPATH for each web application is the unpacked files under WEB-INF/classes plus the jar-files under WEB-INF/lib. And only that. This means the global CLASSPATH variable is ignored. This has been found to be a VERY good thing, so the concept has migrated elsewhere.
For instance a "executable jar" (which Eclipse calls a "runnable jar") which is invoked with "java -jar foobar.jar" contains the complete classpath INSIDE the Jar in a special manifest file. Java Web Start which is used to start java programs from a web server explicily lists the full classpath in the configuration file on the server.
But, to get you started. If you want to write a Java web application:
Get the Eclipse Java EE version.
Create a new Dynamic Web Project e.g. named foobar.
Drag and drop (or copy/paste) the jar files you need in foobar/WebContent/WEB-INF/lib
Create a new file named foobar/WebContent/index.jsp. In the blank file type <h1>Hello World <%= new java.util.Date() %></h1>
Right click in editor for index.jsp, choose Run -> Run on Server, and choose the Basic -> J2EE preview at localhost server, and Finish.
A browser window will now open, either in a browser or inside Eclipse which will render your JSP-page. You can change the JSP-page, save it with Ctrl-S and reload the browser window to see the changes.
Also, I know that WEB-INF\LIB is a place where you can put JAR files that your web app is going to use. However, I've put JARs in WEB-INF\LIB only to have them be ignored. In what situations should I put JARs into WEB-INF\LIB folder? How do I get Eclipse or the web server to notice them?
The real problem you have here is likely that you didn't got Eclipse for Java EE developers and/or that you just created a generic Java Project instead of a Dynamic Web Project and built up the necessary folder structure yourself.
If you create a Dynamic Web Project in Eclipse for Java EE developers, then Eclipse will automagically add any libraries in WEB-INF/lib to the build path. The build path is roughly said just the classpath which is been used in both compiletime and runtime. With other words: just drop the 3rd party JAR's in there, really nothing more needs to be done.
Note that Java is case sensitive, thus it should be really called WEB-INF/lib, not WEB-INF/LIB. But anyway, if you create a Dynamic Web Project, then Eclipse will just automagically generate the correct folder/file structure for you.
As said by others, ignore the %CLASSPATH% environment variable. It is only used by javac.exe/java.exe and even then only when you do not specify any of the -cp, -classpath or -jar arguments. In real world this environment variable is seldom used, it is just some convenience for starters (and unfortunately also the most confusing one, they should never have invented it).
If you're dealing with web applications, /WEB-INF/lib is the portable place to put JARs. This is where web servers servlet containers expect to find an application's jar files.
Eclipse requires you to specify the path to your libraries, jar files (on Properties -> Java Build Path -> Libraries tab). This can be found on the .classpath project file.
Usually you have the JRE libs on its path (which would be on your classpath too), so adding the libs to the classpath and updating eclipse build path would work.
The WEB-INF directory should be the place that contains necessary information for your web application.
I'm not an Eclipse expert, but I think that your problem can be answered like this:
1) CLASSPATH is an environment variable that is read in when you launch java programs and is used by classloader to figure out where the classes are placed.
I would modify the CLASSPATH variable only in the case when you are launching an java program from a script, as this allows you to conveniently launch a program and make sure that the classes are found. This would not be the case for you, as you are developing the web application.
2) WEB-INF/lib is the directory under which the web application container's classloader (like tomcat or glassfish) looks into if your web application needs to resolve a class. So you put there the classes that are used in your web application.
Some IDE's do include the libraries/.jar files that you are using in a project automatically to the package.
3) Eclipse library/classpath resolving during the development time. I would assume, but apologies for assuming, as one really shouldn't do this ;), that you can define a library (add external .jar files to projects) and autocomplete/all the other interesting features should start working with this, as you basically make those classes visible for the IDE with that activity. I also would assume that you can then mark those libraries to be automatically added to the web projects etc., by the IDE.
In general a good reading about how classes are found during execution is here (it's a sun's official documentation). Also a good place to read about this is the ClassLoader class documentation.
Taken together the comments helped me as well. I had added all the jena .jars to the build path from eclipse but that wasn't sufficient. Following suggestion to "add to WEB-INF/lib" it seemed intuitive to drag from libraries folder to WEB-INF (from within eclipse), but that didn't work. Nor did copying the .jars to WEB-INF. I eventually drag-and-dropped from the windows desktop to the WEB-INF lib folder in Eclipse, and that fixed the problem. It would be nice if any .jars added to the build path were automatically copied to WEB-INF lib by Eclipse. In case it matters, this was eclipse EE IDE, Indigo release, on windows 7.

How to add /usr/share/java libs to webapp's classpath?

Summary
Is that possible for webapps deployed on linux + tomcat5.5 to use/see all /usr/share/java/ jars automatically?
Details
I'm packaging my java webapp for Ubuntu (yet the question is related to any linux-based distro) and going to make it depend on tomcat.
I'm going to put context descriptor (an xml file) to /usr/share/tomcat5.5/conf/Catalina/localhost/ to make my app deployed.
Having my web dir here: /usr/share/<appname>/web, how can I enable my app to use java jar libs installed in the system (/usr/share/java)?
I can't just symlink /usr/share/java -> <webdir>/WEB-INF/lib, since I have my custom jars need to be placed in lib dir.
Bad Solution
The solution I've found so far is to symlink each required jar to <webdir>/WEB-INF/lib/.
This is not so good, because I have to symlink a lot of jars and even worse to symlink all jars my direct dependency lib (jar) requires (and so on). In case my direct dependency lib changes its list of required jars I'll have to maintain that symlinks.
According to the Tomcat classloading documentation, you need to put any shared libs that should be available to all Tomcat apps in the $CATALINA_BASE/shared/lib library -- so one way to do what you're looking to do is to move your libraries from /usr/share/java to $CATALINA_BASE/shared/lib.
BUt if I'm not misunderstanding that same documentation, Tomcat also makes the system-wide CLASSPATH variable's contents available to the classloader at launch, so if your directory -- /usr/share/java -- were included in the system-wide CLASSPATH variable, then that should work too. I've never done this, though; Tomcat's method of making the contents of $CATALINA_BASE/shared/lib available Tomcat-wide has always served me perfectly.
entzik's answer lead me to the following solution.
I'm going to use modified "bad solution" (see question).
Modifications are following:
Depend on specific package version for all dependencies (affects "control" file while packaging for deb)example: libcommons-io-java ( = 1.3.1) instead of just libcommons-io-java
Symlink to actual jar files in `/usr/share/java` and not "generalized" onesexample: webdir/WEB-INF/lib/commons-io.jar -> /usr/share/java/commons-io-1.3.1.jarand notwebdir/WEB-INF/lib/commons-io.jar -> /usr/share/java/commons-io.jar
This modifications ensure webapp is not broken if administrator installed new version of a library (commons-io for example).
The downside is this approach clearly inflates system with used-by-only-one-app versions of libraries and may lead to problem some other application/library can't install due to version conflict. I guess both potential problems are minor if we are speaking about libraries.
You have two options, one is to let the classloader provide the libraries to all java programs and the other is to let the classloader provide the libraries to all tomcat contexts.
Add your symlinks to /usr/lib/jvm/java-1.5.0-sun-1.5.0.11/jre/lib (note you may need to specify a different version in this path) to allow all java programs access to these libraries or add them to Tomcat's shared libraries at var/lib/tomcat5.5/shared/libs (again, the version number may be different) for access by all Tomcat contexts.
I should also note that these directory locations were taken from Ubuntu "Feisty".
You should not do that. Java EE applications are the supposed to be self sufficient and not depend on any resources outside the deployment package other than those provided by the container. So you should take the libs you need from that directory and add it to your war or ear package.
This guarantees that your application will behave the same wherever you deploy it and you will not be subject to unexpected changes in the versions of the libs in /usr/share/java....

Categories