• Post Reply Bookmark Topic Watch Topic
  • New Topic

Importing my own JARs in servlets  RSS feed

 
Michael Portman
Ranch Hand
Posts: 129
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello all.

I've written a custom java class which handles all of my file IO stuff. I've Jar'd it up successfully using the following command prompt line:




My FileSystem code is:



Servlet:



When I come to compile my servlet I get the following error:



I've put the FileSystem.jar in my webapps/root/web-inf/lib folder as well.

I'm quite new to java so please be easy on me lol. Help much appreciated! Cheers!
 
Paul Clapham
Sheriff
Posts: 22708
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can't import classes from the unnamed package. If you want to use that FileSystem class in a servlet, you'll have to put it in a package (and import it from that package).
 
Ron McLeod
Bartender
Posts: 1602
232
Android Angular Framework Eclipse IDE Java Linux MySQL Database Redhat TypeScript
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You need to import the class, not the package.

Since your package is named FileSystem (package names should use all lowercase) and your class is named FileSystem, you should importing FileSystem.FileSystem .

Also, class names should begin with a capital, so your servlet class should be named Files, not files.
 
Michael Portman
Ranch Hand
Posts: 129
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ron McLeod wrote:You need to import the class, not the package.

Since your package is named FileSystem (package names should use all lowercase) and your class is named FileSystem, you should importing FileSystem.FileSystem .

Also, class names should begin with a capital, so your servlet class should be named Files, not files.


Ok thanks. I did what you said and now im getting this error:



Any ideas? Cheers
 
Paul Clapham
Sheriff
Posts: 22708
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There's a class named java.io.FileSystem in the standard API, and you're importing that because you import "java.io.*". So there's confusion between that class and your class.

You could solve that by only importing the classes you actually need from the java.io package instead of importing all of them. Like the way you did it in your FileSystem class.
 
Michael Portman
Ranch Hand
Posts: 129
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul Clapham wrote:There's a class named java.io.FileSystem in the standard API, and you're importing that because you import "java.io.*". So there's confusion between that class and your class.

You could solve that by only importing the classes you actually need from the java.io package instead of importing all of them. Like the way you did it in your FileSystem class.


Could I just rename FileSystem to something else? Will that work?
 
Michael Portman
Ranch Hand
Posts: 129
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok I changed my servlet to this:



Now I'm getting this error:



Any more ideas? I feel so useless
 
Tim Moores
Saloon Keeper
Posts: 3961
94
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think you'd be avoiding all sorts of confusion if you renamed the package to "filesystem", and the class to something that doesn't clash with a class from the JAVA class libraries.

This look suspicious:
D:\Apache Software Foundation\Tomcat 7.0\webapps\ROOT\WEB-INF\classes\evo\test>javac files.java

Source code shouldn't be in the classes directory; those should be kept separately.
 
Stephan van Hulst
Saloon Keeper
Posts: 7932
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You need to tell the compiler where your dependencies are. You can specify the location of your library jar with the -classpath switch.

Alternatively, you can use Maven to handle all your dependencies.
 
Dave Tolls
Ranch Foreman
Posts: 3009
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There's a number of things going on here, but the root seems to be this:


That is jarring up the FileSystem class by itself, excluding any package directory it is in.

However, your class is declared as being in a package:


So your jar file is incorrect.
It should be created using something like:

where 'FileSystem' is the directory containing the class file.
 
Michael Portman
Ranch Hand
Posts: 129
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok theres quite a few different opinions going on here from different people and im getting confused lol. So I'm gonna start again...

Ok for simplicity I've made a new partition called J:\ (labeled Java Dev) from my 3TB HDD. All my Java work is gonna go in there.

In this new HD (partition) ive made 3 folders, one called 'classes', one called 'jars', and one called 'source'.

I've renamed FileSystem.java to evoFileSystem.java (as evo is my nickname lol) and I've put it into the source folder (J:\source\).

I've decided that I want evoFileSystem.java to be part of a package called evoEngine. So in the evoFileSystem source code should give it the package name 'evoEngine'? If so how would I JAR it up so it makes evoEngine.evoFileSystem? Because that's what I'll need it to be when I come to call it in my servlets. I'm gonna need a quick guide on how to do this from one of you guys which would be VERY much appreciated! Remember the file structure I've created IE J:\classes, J:\source, an J:\jars.

Thanks guys!
 
Michael Portman
Ranch Hand
Posts: 129
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Right ok. I've failed again lol. This is what I've done, I'll explain step by step...

1. Renamed FileSysem to evoFileSystem.
2. Gave it a new package name called evoEngine:



3. Compiled it at J:\source\ javac evoFileSystem.java.
4. Compiled successfully.
5. Made a manifest called manifest.mf with the following contents:



6. JAR'd it up at J:\source\ jar cfm evoEngine.jar manifest.mf evoFileSystem.class
7. JAR'd successfully.
8. Now I have evoEngine.jar with evoFileSystem.class contained in it.
9. Created a test servlet called files2 with the following code:



10. Tried to compile it where I normally compile my test servlets at (D:\Apache Software Foundation\Tomcat 7.0\webapps\ROOT\WEB-INF\classes\evo\test) javac files2.java

Now I'm getting the following compile time error:



The evoEngine.jar is in my D:\Apache Software Foundation\Tomcat 7.0\webapps\ROOT\WEB-INF\lib folder as well. Where am I going wrong guys? I have a feeling its something to do with the manifest file. Help appreciated!!!
 
Stephan van Hulst
Saloon Keeper
Posts: 7932
143
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Michael Portman wrote:1. Renamed FileSysem to evoFileSystem.

Don't start type names with lowercase. Call it EvoFileSystem.

3. Compiled it at J:\source\ javac evoFileSystem.java.

So now you have compiled class in your source directory. Not good. Use the -d switch to specify the folder where your compiled classes should go.

5. Made a manifest called manifest.mf with the following contents:

But the fully qualified name of your main class is evoEngine.evoFileSystem. Besides, why does your library have a main class in the first place?

6. JAR'd it up at J:\source\ jar cfm evoEngine.jar manifest.mf evoFileSystem.class

So now you have a JAR in your source directory. Not good. Use your jars folder in the path of the created JAR.

8. Now I have evoEngine.jar with evoFileSystem.class contained in it.

Yes, but it's not in the right location inside the JAR file. It's located at the root directory, but it needs to be inside a directory named after your package. Instead of using evoFileSystem.class as the command line argument, use evoEngine.

9. Created a test servlet called files2 [...]

Again, type names should start with uppercase.

10. Tried to compile it where I normally compile my test servlets at (D:\Apache Software Foundation\Tomcat 7.0\webapps\ROOT\WEB-INF\classes\evo\test) javac files2.java

You didn't tell the compiler where to find the library containing your file system. Use the -classpath switch to do this.

The evoEngine.jar is in my D:\Apache Software Foundation\Tomcat 7.0\webapps\ROOT\WEB-INF\lib folder as well.

This is not used by your compiler, only for your servlet container to find the dependencies at runtime.
 
Stephan van Hulst
Saloon Keeper
Posts: 7932
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I question your choice to have a single location where the sources, compiled classes and libraries of all your projects are. In your J:\ partition, you should have one directory per project. Inside your project directory it's convention to use src\ for sources, and target\classes\ for compiled classes. Personally, I also like to copy the final artifact to a dist\ folder. Let's make an example:

ExampleLibrary.java

ExampleApplication.java

MANIFEST.MF

Example Library\build.bat

Example Application\build.bat
 
Dave Tolls
Ranch Foreman
Posts: 3009
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
First off, when you place a class in a package it is supposed to go in a folder with the same name as the package.  So your new class should be in an evoEngine folder.
Java expects this structure.

Second (and this is the same as my earlier point) this structure needs to be maintained in the jar file, so you need to jar the folder, and not just the class.
I would have expected the class file to be created as evoEngine/evoFileSystem.class, so the jar command wouldn't have worked from the sources directory.

Third, as Stephan has said, the Manifest has the wrong class name.  Out of curiosity, did you do a test run of the jar file to see if it would actually run?
 
Tim Holloway
Bartender
Posts: 18779
74
Android Eclipse IDE Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Short synopsis:

1. All classes belong to a package. If you don't put a "package" statement at the top of your class source code file, the class will be assigned to the default package which has no package name. A LOT of tools don't like the default package, so you should always define an explicit package.

2. A package name is a tree construct like a file directory. For example, "java.lang.utils". The package name component separators are "." characters. Each package name component MUST adhere to certain lexical standards as defined in the Java Language Specification. Briefly, only letters, digits, and underscores. There are other options, but these are all you should use unless you know better.

3. Java is a case-sensitive language. The package name components should not start with a capital letter. In fact, caps are best not used in package name components.

4. In actual practice, the source class files should be arranged in a subdirectory tree that matches the package component tree. That is, put the com.coderanch.utils class files in the source directory com/coderanch/utils. NOTE that while some OS's ignore letter case in filenames, Java does not, so naming the directories Com/Coderanch/Utils is a big no-no, even if the OS would prefer to do it that way.

The actual rule in Java is that class names are capitalized, but resource names (instances and members, for example) are not. So If I want a file I/O class, I'd name it something like FileIO. The file itself would be com/coderanch/utils/FileIO.java and the compiler would produce a file names com/coderanch/utils/FileIO.class.

When you take all the classes and build a JAR, the pathnames of the class resources in the JAR are relative to the package root. So if the actual filesystem location was C:/users/chad/project1/classes/com/coderanch/utils/FileIO.class, a jar directory listing would show "com/coderanch/utile/FileIO.class".

AND FINALLY.

To use the JAR in your webapp, all that's needed is to include the JAR under the webapp's WEB-INF/lib directory. You don't need a Main-Class in the manifest, since webapps are not executable programs and this is a library, not a program anyhow.

When the server deploys the webapp, it will look under WEB-INF, add the WEB-INF/classes directory to the webapp's classpath, and scan each JAR in WEB-INF/lib, adding the classes it finds in the JARs (this is different than how stand-alone application classpaths work). A custom classloader is created for each webapp deployed in a server, and each of those webapp classloaders sees only the classes/jars that are part of that webapp. So if I deploy 2 webapps - app1 and app2 and app1 has a WEB-INF/lib/myfileio.jar, the classes in that JAR will not be found by code in app2. You'd have to include a separate copy of myfileo.jar in the WEB-INF/lib of app2 for app2's classes to see them.
 
Michael Portman
Ranch Hand
Posts: 129
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tim Holloway wrote:Short synopsis:

1. All classes belong to a package. If you don't put a "package" statement at the top of your class source code file, the class will be assigned to the default package which has no package name. A LOT of tools don't like the default package, so you should always define an explicit package.

2. A package name is a tree construct like a file directory. For example, "java.lang.utils". The package name component separators are "." characters. Each package name component MUST adhere to certain lexical standards as defined in the Java Language Specification. Briefly, only letters, digits, and underscores. There are other options, but these are all you should use unless you know better.

3. Java is a case-sensitive language. The package name components should not start with a capital letter. In fact, caps are best not used in package name components.

4. In actual practice, the source class files should be arranged in a subdirectory tree that matches the package component tree. That is, put the com.coderanch.utils class files in the source directory com/coderanch/utils. NOTE that while some OS's ignore letter case in filenames, Java does not, so naming the directories Com/Coderanch/Utils is a big no-no, even if the OS would prefer to do it that way.

The actual rule in Java is that class names are capitalized, but resource names (instances and members, for example) are not. So If I want a file I/O class, I'd name it something like FileIO. The file itself would be com/coderanch/utils/FileIO.java and the compiler would produce a file names com/coderanch/utils/FileIO.class.

When you take all the classes and build a JAR, the pathnames of the class resources in the JAR are relative to the package root. So if the actual filesystem location was C:/users/chad/project1/classes/com/coderanch/utils/FileIO.class, a jar directory listing would show "com/coderanch/utile/FileIO.class".

AND FINALLY.

To use the JAR in your webapp, all that's needed is to include the JAR under the webapp's WEB-INF/lib directory. You don't need a Main-Class in the manifest, since webapps are not executable programs and this is a library, not a program anyhow.

When the server deploys the webapp, it will look under WEB-INF, add the WEB-INF/classes directory to the webapp's classpath, and scan each JAR in WEB-INF/lib, adding the classes it finds in the JARs (this is different than how stand-alone application classpaths work). A custom classloader is created for each webapp deployed in a server, and each of those webapp classloaders sees only the classes/jars that are part of that webapp. So if I deploy 2 webapps - app1 and app2 and app1 has a WEB-INF/lib/myfileio.jar, the classes in that JAR will not be found by code in app2. You'd have to include a separate copy of myfileo.jar in the WEB-INF/lib of app2 for app2's classes to see them.


Thanks for that very informative post! Ok so heres what ive done...

I've created a evoEngine.jar file by using the following command:



When I open the JAR to check the file structure and to see where my FileIO.class is located it looks like this "evoEngine/utils/FileIO.class

In my FileIO class ive put in the following package definition at the top:



I created a test servlet with the following code:



I put my evoEngine.jar in my webapps/ROOT/WEB-INF/lib folder.

When I try and compile file2.java I get this error message again:



Any reason why java/tomcat can't find my evoEngine.jar?? I've compiled the JAR properly and ive put it in the correct place! Any further would be appreciative!! Thanks. 
 
Dave Tolls
Ranch Foreman
Posts: 3009
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You need to include any dependencies in the classpath of the javac command.

In your case something like:
javac -cp <path to the jar file>:. files2.java

Also, you are still writing your java code inside your webapps directory.
You really need to move this out of there.  It's a bad habit to get into.

Are you learning Java by doing Servlets, by the way?
I'm not sure that's going to be very productive.  There's a lot of parts to a web app, and an IDE really helps when building one.  Even a fairly basic one.
 
Michael Portman
Ranch Hand
Posts: 129
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dave Tolls wrote:You need to include any dependencies in the classpath of the javac command.

In your case something like:
javac -cp <path to the jar file>:. files2.java

Also, you are still writing your java code inside your webapps directory.
You really need to move this out of there.  It's a bad habit to get into.

Are you learning Java by doing Servlets, by the way?
I'm not sure that's going to be very productive.  There's a lot of parts to a web app, and an IDE really helps when building one.  Even a fairly basic one.


Ok I set my classpath to the following in command prompt:



Now I'm getting a new error lol:

 
Dave Tolls
Ranch Foreman
Posts: 3009
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You're still trying to work in the webapps directory.

In addition, your jar file is intended for your webapp, not Tomcat as a whole, so shouldn't be in the Tomcat lib directory.

Your jar file looks like it has an issue.
Or possibly your class file itself?

But first off I would move your stuff out into a proper project structure, away from Tomcat.
 
Michael Portman
Ranch Hand
Posts: 129
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dave Tolls wrote:You're still trying to work in the webapps directory.

In addition, your jar file is intended for your webapp, not Tomcat as a whole, so shouldn't be in the Tomcat lib directory.

Your jar file looks like it has an issue.
Or possibly your class file itself?

But first off I would move your stuff out into a proper project structure, away from Tomcat.


Ok I'll see what i can do. The problem I've got is I'm coding/deploying it like I would with a PHP app. I'm mainly a PHP developer, I've been developing PHP webapps for about 15 years. I want to learn Java to the same level of my PHP knowledge. The main reason why I want to learn Java and only use Java is because Java jobs in my country pay more than PHP. I live in the UK.
 
Stephan van Hulst
Saloon Keeper
Posts: 7932
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can usually set up your IDE to automatically redeploy the application when you save it. I work with NetBeans, and when I edit a line of code in my application and save it, it immediately becomes visible in my browser, even though the project lives far far away from Tomcat.

If you want to do this with the command line, I suggest you use a build tool like Maven. If you've set up your project descriptor correctly, all you have to do is type "mvn package" and it will retrieve your dependencies, compile the application, test it, package it and copy the package to the servlet container.
 
Tim Holloway
Bartender
Posts: 18779
74
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am not a big proponent of using an IDE as a crutch to learn the basics of a system. From experience, I can tell you that it can persuade you to  do horrible things and get a really warped view of how things work. Avoid "Wizards" at all cost until you understand the platform well enough to know what the wizards actually do. Which typically isn't as much as you need them to do. Wizards were intended to help people, but too often pointy-haired boss types think that if a wizard can write the code, then the intelligence (hence, the salary) of the developer can be lower. In case you're wondering where my signature line comes from.

Having said that, I do recommend using a build tool to create the JAR and the WAR. That's because setting up anything but the simplest compile for Java can be really gnarly. Popular build tools include Ant (based on explicit instructions coded in XML), Maven (which is mostly magic, but it knows how to do common things), Gradle (can also do non-Java projects), and others. We have a Maven/Ant forum here that is very active.

Do not drop random JARs into the TOMCAT_HOME/lib directory. The execution environment for classes in that directory is much different than it is within a webapp.

What Stephan is trying to say is that you have 2 environments. The build environment, where you compile and assemble your JAR and your webapp, and the runtime environment, where you deploy the app into Tomcat. This contrasts with PHP and similar scripting platforms where you can just plop raw source code directly into the deployed application.

The build stage has 2 parts. The first part is to build the JAR. This is pretty simple. Once you have the JAR, you'll build the webapp (WAR), including the JAR into the output WAR. Maven has pre-built functions for both of these actions. And, just to warn you, Maven only likes to create one output per project, so you'd have one project for the JAR and another one for the webapp. And you could have a third master project that ensures that the jar and WAR are built in the right order.

Once you have your WAR file, you can copy it into the TOMCAT_HOME/webapps directory. However, note that the application's URL context will be the same as the name of the WAR. So mywebapp.war will be exploded by Tomcat into mywebapp and the corresponding URL would be http://localhost:8080/mywebapp. Also, once exploded, the war directory takes precedence over a WAR file, so if you update the WAR file, delete the old war directory!

The directory TOMCAT_HOME/webapps/ROOT is a special creature. By convention, the name of the webapp directory is the same as the URL context name. However, the default root webapp (which is generally pre-installed), has no context name. It's context path is simply "/". That is, "http://localhost:8080/". Since "/" is not a valid filename under most OS's, Tomcat uses the directory named "ROOT" for that context. And, as I mentioned, most Tomcat distros come with a pre-installed root webapp, so if you go plunking your own files into ROOT, you're likely to damage the existing app, plus your own code may behave unpredictably. You could simply replace the ROOT webapp, but as a rule, I don't recommend that.
 
Don't get me started about those stupid light bulbs.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!