Wednesday, February 18, 2009

How to run Tomcat manager web application

1. Add the security role manager to $CATALINA_HOME/conf/tomcat-users.xml, and assign this role to a username, say tomcat:

  

2. Start Tomcat:
$CATALINA_HOME/bin/startup.sh
(%CATALINA_HOME%\bin\startup.bat on windows)
3. Browser the URL http://localhost:8080, and click the Tomcat Manager link on the upper-left corner. In the basic login page, enter username tomcat and password tomcat, as specified in conf/tomcat-users.xml. Tomcat Manager web application allows you to view Tomcat server info, deploy and undeploy webapps, and other simple management tasks.

How to run Tomcat on a different port number

Tomcat web server by default runs on port number 8080, which is also the default port number used by some other popular servers like JBoss, JavaEE SDK, Sun Java System Application Server. When this port number is already used by another process, you will get the following error:

logs/catalina.2007-01-09.log:

...
INFO: Starting Servlet Engine: Apache Tomcat/5.5.20
Jan 11, 2007 9:36:12 AM org.apache.catalina.core.StandardHost start
INFO: XML validation disabled
Jan 11, 2007 9:36:13 AM org.apache.coyote.http11.Http11BaseProtocol start
SEVERE: Error starting endpoint
java.net.BindException: Address already in use: JVM_Bind:8080
at org.apache.tomcat.util.net.PoolTcpEndpoint.initEndpoint(PoolTcpEndpoi
nt.java:297)
at org.apache.tomcat.util.net.PoolTcpEndpoint.startEndpoint(PoolTcpEndpo
int.java:312)
at org.apache.coyote.http11.Http11BaseProtocol.start(Http11BaseProtocol.
java:150)
at org.apache.coyote.http11.Http11Protocol.start(Http11Protocol.java:75)

at org.apache.catalina.connector.Connector.start(Connector.java:1089)
at org.apache.catalina.core.StandardService.start(StandardService.java:4
59)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:709
)
at org.apache.catalina.startup.Catalina.start(Catalina.java:551)
To use a different port number, back up and edit the port attribute value of Connector element in $CATALINA_HOME/conf/server.xml:


Restart Tomcat ($CATALINA_HOME/bin/startup.sh on Unix or %CATALINA_HOME%\bin\startup.bat on Windows), and check server status at URL http://localhost:8081

Line tools NetBeans plugin

I don't like overloading my IDE with a bunch of plugins, but this is a must-have for my NetBeans (currently version 5.5.1).

[Update] Those features in line tool has been integrated into NetBeans proper 6.x. So if you are running NetBeans 6.1 (the latest as of 5/2008), line tool plugin is no longer needed.

I use it everyday to copy and paste lines of text without using CTRL-C CTRL-V. This is its official description:

Line Tools Support following operations in text editors:

1. Move Line (or lines spanned by selection) Up

2. Move Line (or lines spanned by selection) Down

3. Copy Line (or lines spanned by selection) Up

4. Copy Line (or lines spanned by selection) Down

5. Sort lines spanned by selection in ascending order

6. Sort lines spanned by selection in descending order

7. Remove duplicate lines while sorting. Maintain the caret position, the selection and the order of start and end of the selection when moving/copying the lines.


This is the first plugin I will install for every new NetBeans release. Unfortunately, NetBeans can't automatically migrate my installed plugins.

Oddly, this plugin doesn't show up in the official NetBeans plugin portal. The place to go is the author's (Sandip Chitale) blog.

You can choose either download the *.nbm file and manually install it, or add a new update center (Sandip Chitale's update center) to your NetBeans. After adding the update center, you will able to download a lot more good stuffs by Sandip Chitale.

Tuesday, February 17, 2009

A New Option in Jar Command in JDK 6

JDK 6 adds a new feature to the jar command: e. Other options of the jar command are still the same. This is the partial usage from JDK 6 beta 2:

C:\tools\jdk6\bin>jar
Usage: jar {ctxui}[vfm0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...
Options:
...
-e specify application entry point for stand-alone application
bundled into an executable jar file
...
For example, I run jar command to package a self-contained application in a jar file:
C:\ws\nb\scrap\build\classes>C:\tools\jdk6\bin\jar cvfe  ..\..\dist\hello-world.jar com.javahowto.test.HelloWorld com
added manifest
adding: com/(in = 0) (out= 0)(stored 0%)
adding: com/javahowto/(in = 0) (out= 0)(stored 0%)
adding: com/javahowto/test/(in = 0) (out= 0)(stored 0%)
adding: com/javahowto/test/HelloWorld.class(in = 572) (out= 348)(deflated 39%)
Then I can distribute hello-world.jar to users, who can run hello-world app like this:
C:\download\hello>java -jar hello-world.jar
Hello world!
Users can run it with any version of java; it doesn't have to be JDK 6. What the extra e option does is simply adding a Main-Class entry in the jar's META-INF\MANIFEST.MF:
Manifest-Version: 1.0
Created-By: 1.6.0-beta2 (Sun Microsystems Inc.)
Main-Class: com.javahowto.test.HelloWorld
This new feature is helpful when packaging simple self-contained apps, and application client modules in J2EE/JavaEE, both of them require a Main-Class entry in MANIFEST.MF. So I don't have to create one beforehand, or have Apache Ant generate one.

Something You May Not Know about Jar Command

1. jar command can also operate on zip files. I usually run jar tvf hello.zip to quickly view its content, without starting up the WinZip program. jar xvf hello.zip should also be able to expand the target zip files. I find it hard to memorize Unix zip/unzip command line options, so I just use jar tvf/jar xvf instead. For example:

C:\tmp>jar tvf eclipse-SDK-3.2RC7-win32.zip
2. jar tvf can selectively list table of contents for archive. I used to run jar tvf j2ee.jar | grep javax/servlet/http to search for servlet classes in j2ee.jar. Replace grep with findstr on Windows. In fact, I don't need grep or findstr; I can just run this command:
jar tvf j2ee.jar javax/servlet/http
Note that the search criteria are matched against the beginning of all entries in jar file. It uses String.startsWith(what) rather than String.contains(what). So this command jar tvf j2ee.jar ejb will not return any matching entries, though jar tvf j2ee.jar javax/ejb will return all ejb classes. The search is also case-sensitive.

If you want case-insensitive search, or match by any parts (not just the beginning) of entries, you still need to use jar tvf my.jar | grep -i aNynAmE

3. You can extract selected entries from a jar file. For instance, if you only want to view the meta-inf/manifest.mf file, you can
C:\Sun\AppServer\lib>jar xvf j2ee.jar META-INF/MANIFEST.MF
inflated: META-INF/MANIFEST.MF
Or using a backslash instead of a forward slash:
C:\Sun\AppServer\lib>jar xvf j2ee.jar META-INF\MANIFEST.MF
inflated: META-INF/MANIFEST.MF
The entry names are case sensitive, and so the following will not extract anything:
C:\Sun\AppServer\lib>jar xvf j2ee.jar meta-inf/manifest.mf
Of course, you can always double-click the entry to view it in WinZip, fileroller, or other tools.

4. You can choose not to have manifest file when creating a jar file, using M option:

jar cvfM no-meta.jar A.class
adding: A.class(in = 405) (out= 279)(deflated 31%)
Note: it's upper-case M. Lower-case m has a different meaning.

5. You can specify your own manifest file when creating a jar file, using m option:
jar cvfm my-meta.jar my-meta-inf\my.mf A.class
added manifest
adding: A.class(in = 405) (out= 279)(deflated 31%)
The option used here cvfm tells the jar command that the destination file (f) will come next and then custom manifest file (m). I can also specify them in a different order:
jar cvmf my-meta-inf\my.mf my-meta.jar A.class
added manifest
adding: A.class(in = 405) (out= 279)(deflated 31%)
It's lower-case m. Upper-case M has a different meaning.

6.META-INF/MANIFEST.MF file in source files is always ignored.
jar cvf ignore.jar A.class META-INF
added manifest
adding: A.class(in = 405) (out= 279)(deflated 31%)
ignoring entry META-INF/
adding: META-INF/LICENSE.txt(in = 2657) (out= 1185)(deflated 55%)
ignoring entry META-INF/MANIFEST.MF
When it comes to manifest files for new jar file, you only have 3 options:
  • Do not specify any manifest-related options and use the default MANIFEST.MF

  • Use option M not to include a manifest file

  • Use option m to use a custom manifest file. Inside the jar file, this file will always be named MANIFEST.MF under META-INF directory. Outside of the jar file, this custom manifest file can be anywhere and have any name.
7. If you unjar an archive, do nothing, and then jar it up again, the resulted new archive may not equal to the original one. And applications using this new archive may not work correctly because of the wrong manifest file. The original jar may have a custom manifest file, which is expaned into META-INF/MANIFEST.MF. But when you jar these files up again without using cvfm option, this custom manifest file is ignored and a default MANIFEST.MF is included.

8. jar command options can start with optional -. jar tvf a.jar is the same as jar -tvf a.jar

9. You would usually use relative paths for source files, relative to the current directory. These relative paths will be preserved inside the target jar file. For example, jar cvf \tmp\b.jar com\javahowto\test\ will create the directory tree com\javahowto\test\ inside the target jar, and include all files under \com\javahowto\test\.

If you use absolute paths for source files, jar will copy the absolute paths inside the jar file, which is not what you want. For example,

C:\tmp>jar cvf a.jar C:\tmp\A.class
added manifest
adding: C:/tmp/A.class(in = 405) (out= 279)(deflated 31%)
10. If source files are not located in the current directory, you can use -C option to tell jar command to implicitly change to another directory and then include files there. For example,
C:\ws\nb\scrap\dist>jar cvf hello-world.jar -C ..\build\classes com\javahowto\test
11. If you use -C ../build/classes option and want to include all files under ../build/classes, use . (dot) to represent all files there. Note that you can't use *, which will resolve by OS to all files to the current directory. For example,
C:\ws\nb\scrap\dist>jar cvf hello-world.jar -C ..\build\classes .
The following example (using -C and *) will ignore -C option and instead include all files in the current directory, which is not what we want:
C:\ws\nb\scrap\dist>jar cvf hello-world.jar -C ..\build\classes *
..\build\classes\com\hello-world.jar : no such file or directory
added manifest
adding: scrap.jar(in = 20487) (out= 7472)(deflated 63%)
12. There are 3 types of paths in jar command:
  • path to the destination jar file, either relative or absolute path is fine. In fact, any format is ok as long as it can be correctly resolved by the OS

  • path to the manifest file, if m option is present. Either relative or absolute path is fine. The same as destination file.

  • multiple paths to source files. They should be relative to the current directory, unless -C option is present. In that case, all source files should be relative to the value of -C option.
If you don't like using -C option, I'd suggest you always cd into the parent directory of all source files, and then run jar command.

13. It is not possible to include source files from multiple different parent directories. But you can always first copy them into a common parent directory. Jar task in Apache Ant is more flexible and can accommodate almost all use cases.

14. In JDK 6 or newer version, you can use e option to specify an entry-point class (Main-Class in META-INF/MANIFEST.MF) for self-contained applications packaged in a jar file. See this post for details.

JDK 6 Supports * in Classpath But Be Aware of This

Finally JDK 6 (Mustang) lets me use wildcard (*) in classpath. I no longer have to enumerate all jar files in a lib directory. But with this added feature, it's easier to get errors like "javac: invalid flag:" For example, I want to complile a simple servlet, including all jar files in C:\Sun\AppServer\lib:

C:\tmp> javac -cp C:\Sun\AppServer\lib\*
HelloWorldServlet.java
javac: invalid flag: C:\Sun\AppServer\lib\addons
Usage: javac
use -help for a list of possible options
What's happening here is, the OS expands * to all files/directories in C:\Sun\AppServer\lib, since * has special meaning for the OS. So the real command resolves to:
javac -cp C:\Sun\AppServer\lib\activation.jar
C:\Sun\AppServer\lib\addon
C:\Sun\AppServer\lib\admin-cli.jar
C:\Sun\AppServer\lib\ant ... HelloWorldServlet.java
As all files/directories are expanded alphabetically, the first one (activation.jar) is treated as classpath element, and everything else starting with addon are treated as separate JVM options. Of course these are invalid JVM options, hence javac: invalid flag:

Note: if you are using javaw.exe instead of java.exe, * wildcard expansion in -cp or -classpath doesn't work, due to JDK 6 bug 6510337

So here are some tricks how to use * in classpath without getting burned:
  • Quote it, if your classpath has a single element that uses *. For example,
    javac -cp "C:\Sun\AppServer\lib\*" HelloWorldServlet.java
  • This problem doesn't exist if you have more than one element in classpath, even though they do not exist:
    javac -cp C:\Sun\AppServer\lib\*;\nosuchdir HelloWorldServlet.java
  • This problem exists for all JDK tools that takes classpath option, including java. The error is different but solution is the same as above.
    java -cp C:\temp\* A
    Exception in thread "main" java.lang.NoClassDefFoundError: C:\temp\b/jar
  • Of course, if the directory contains 1 jar file, it will be expanded correctly, and you don't need to quote it. But using * doesn't save you much typing:
    java -cp C:\single-jar-file-folder\* A
    this is A

6 Ways of Setting Java Classpath

How to set Java classpath? List as many ways as you can. This can be an interesting Java job interview question. Here are what I came up with:

  1. Use -classpath JVM option:
    java -classpath C:\hello\build\classes com.javahowto.test.HelloWorld
  2. Use -cp JVM option, a short form of -classpath:
    java -classpath C:\hello\build\classes com.javahowto.test.HelloWorld
  3. Use -Djava.class.path system property:
    java -Djava.class.path=C:\hello\build\classes com.javahowto.test.HelloWorld
  4. Use CLASSPATH environment variable:
    set CLASSPATH=C:\hello\build\classes;
    java com.javahowto.test.HelloWorld
  5. Use current directory as the default classpath:
    cd C:\hello\build\classes;
    java com.javahowto.test.HelloWorld
  6. Package all classes into a self-containing jar file that has this in its META-INF/MANIFEST.MF.
    Main-Class: com.javahowto.test.HelloWorld
    java -jar hello-world.jar
    Note: when you run java with -jar option, any -classpath, or -cp options are ignored, as JVM thinks all classes are already contained inside the jar file.
Among all those options, I usually use option 1, and occasionally 6. I don't like my Java apps have dependency on environment settings like CLASSPATH, which is totally unpredictable. Using current directory as the default classpath is not a good idea either, since your classes may be scattered in several directories, folders and jar files.

Can I set classpath at java runtime dynamically and programmatically? No. Although you can set the system property java.class.path in your application, but its new value doesn't affect the system classloader. If you need to reset classpath, it's time to consider using a custom classloader as the child loader of the system classloader.

With a custom classloader, you have full control where to load class files, from local file system, remote url, or even database. Classes loaded by such a custom loader are only visible by this loader and its child loaders, but not to its parent loader nor the system classloader.

For the same reason, you can't dynamically set minimum/maximum heap size of a JVM. These JVM options are all set once when JVM is started and unchanged throughout its life.

JAVA_HOME vs java.home

What's the difference between JAVA_HOME and java.home? JAVA_HOME is the JDK install directory, e.g., C:\jdk5. It's meant to be set as an environment variable and referenced in Windows batch files or Unix scripts. I always have it in my Windows Control Panel and .tcsh files,along with other common environment variables. Some Java applications use the name jdk.home for this purpose, which I think is a better name. But JAVA_HOME has been used since the beginning and is now a convention.

java.home is the JRE install directory, e.g., C:\jdk5\jre, or C:\Program Files\Java\jre1.5.0_06. Unlike JAVA_HOME, I never seen java.home as an environment variable. java.home is a build-in Java system property, whose value is the JRE install directory. Since all Java system properties are also exposed as Ant build properties, you can also use ${java.home} in build files.

Would jre.home be a better name? Maybe, but I don't think Sun will change it.

Therefore, java.home is always there inside JVM, whereas JAVA_HOME exists mainly in your shell environment and you may pass it to JVM as a system property. Why do we still need JAVA_HOME? Well, there are good reasons:

  • You can add $JAVA_HOME/bin to the beginning of your PATH, to make sure you always invoke the right java program. On Windows, java.exe is duplicated in several places, for instance %JAVA_HOME%\bin\java.exe, $JAVA_HOME\jre\bin\java.exe, and %SystemRoot%\system32\java.exe. Without have $JAVA_HOME/bin at the beginning of the PATH, a java command will always resolve to %SystemRoot%\system32\java.exe, which may not be what you want. The same problem can also exist in Linux/Solaris.

  • Some Java application runtime needs to use tools/libraries only available in JDK. For example, web containers need tools.jar in JDK to compile JSP pages, and ejb containers also need to invoke javac/rmic tools in JDK. So the build-in system property java.home is not sufficient.

Java Jar File Naming Conventions and Examples

util.jar is the worst jar file name I can think of. All I know is it contains some utility/helper classes. But it is unclear if they belong to an application server, or a framework, or any application sub-systems. You will need to ask someone or some docs to know what it is. It's part of the DataDirect JDBC Driver distribution.

On the other hand, good jar file names are always self-explanatory, for example: struts.jar, jboss-system.jar, commons-pool-1.1.jar

Some thoughts on jar file naming conventions:

  1. Always use extension ".jar", not ".zip"
    Theoretically, jar files can have any extension or no extension at all. If you specify it in the system classpath, it should be loadable. The problem is with automatic library detection and loading by containers and frameworks. It's expensive to scan all files so some sort of extension restriction is needed. For this reason, J2EE/JavaEE platform spec requires all library jar files use ".jar" extension, such as WEB-INF/lib/mybeans.jar.

  2. Use hyphen (-) instead of underscore (_) as word separator
    First, it's easier to type - than _; secondly, when the file name is underlined (e.g., in a hyperlink), the _ is invisible. Hyphen has been shunned in file names partly because it is an illegal character in java identifier. But this concern is unwarranted.

  3. Append version number if distributed standalone
    because they can be dropped into any applications, which may need specific versions. We don't want users to have to compare file size or extract some META-INF files to know its version. Some examples: hibernate3.jar, commons-logging-1.0.3.jar, and
    log4j-1.2.8.jar
    .

  4. Don't append version number if bundled inside other larger deliverables
    because the enclosing deliverables, such as an application server (e.g., JBoss 4.0.4, jakarta-tomcat-5), a tool(e.g., apache-ant-1.6.5), aleady have the version numbers, thus no version number for jboss.jar, catalina.jar, and ant.jar.

Great Programmers answer questions

I'm not a great programmer, I'd like to think that I'm pretty good at it, but I'm far from great. That being said, for my own ammusement, I'm going to answer these questions as well.

- How did you learn programming? Were any schools of any use? Or maybe you didn’t even bother with ending any schools :) ?
I have a sorted past with school. I was never a good student, and I never went to college. I received some computer training in the Army, but it was pretty much all crap. Some day, I'd like to go back and get a degree, but I don't know how useful the degree itself would be. I learned to program by buying books, lots of books. And just doing it, as much as possible for any reason possible. The key is to be around people that can correct you and can correct you when you hack :)

- What do you think is the most important skill every programmer should posses?
I agree most with James Gosling and Dave Thomas here. Motivation and Passion. Without those it's just a job. Communication skills are what leads you beyond that. You can't lead if nobody understands a damn thing you're saying.

- Do you think mathematics and/or physics are an important skill for a programmer? Why?
Physics? No way. Not unless you work for Blizzard or Id. Math, yes, but again that can be very field dependent. I agree with DHH on his point that most of us work on business problems, not math problems. Though, it wouldn't hurt for me to bump up my math skills they do suck.

- What do you think will be the next big thing in computer programming? X-oriented programming, y language, quantum computers, what?
Who knows. I suppose I'll continue doing what I've always done. Learn what is usefull and interesting. Outside of that, what's the point?

- If you had three months to learn one relativly new technology, which one would You choose?
If I had 3 months to work on anything, it probably means I should be working on my resume.

- What do you think makes some programmers 10 or 100 times more productive than others?Again, Motivition and Passion. I'm always learning, always reading, always on the hunt for something intresting. I'm probably not better than most programmers, I just have more stuff in my head to reference.

- What are your favourite tools (operating system, programming/scripting language, text editor, version control system, shell, database engine, other tools you can’t live without) and why do you like them more than others?
Intellij IDEA. It's simply the best IDE for any language out there.
Ruby is the simplest scripting language I've seen, easy to learn and use.
Well, Java and Ruby are my favorite programming languages. It comes down to using the right tool for the job though.
Operating system, well I'm gonna get burned at the stake for this but I have no problem with Windows XP. It does what I want, it almost always works. And I don't have to edit any f*cking text files to make simple changes.
That being said, I like Ubuntu Linux hehe. I'd love to have a Mac to work on, but I'm simply not willing to buy their hardware. I have PC hardware at home, when I can use that I'm all over it.

- What is your favourite book related to computer programming?
Well, I don't have a personal favorite. I think I'll use the answers as a recommendation list. Except maybe "Gödel, Escher, Bach: an Eternal Golden Braid" as I have no idea what the hell that says.

- What is Your favourite book NOT related to computer programming?
Simply can't answer that one.

- What are your favourite music bands/performers/compositors?
Here's where I look like the white nerd kid from Office Space...
I like Pink Floyd, Zepplin, Korn, Eminiem, 50 Cent, Blues Traveler, Flogging Molly. I've gotten into a bit of classical and soundtracks, they're good for reading. I couldn't name a favorite from those categories though.