Monochromatic

z3bra, the stripes apart

Java without Eclipse

— 08 September, 2013

This is a fact, when someone starts developping with java, he (or she) is given an IDE: Eclipse.

When one codes in C, using plain gcc + Makefile and a good text editor is adviced. This is the same for C++, bash, ruby, haskell, perl, python, bla bla bla...
Why would java escape the rules ?!

Of course, there are advantages ! And if these are good enough for you. Go with eclipse And have some fun !

Throwing Eclipse away

For that to be clear, I am not saying that IDEs are evil ! I am just showing how you can avoid them, in favor of your daily tools.
I just finished a java project for my CS studies, on a bare notebook (without X.org). And I had NO PROBLEM with not using Eclipse at all !
Now let me introduce my setup. Of course, it's not as easy as double-clicking on the eclipse-setup.exe. but it follows my ideas, and I'm happy with it !

It needs the following:

You just have to know how to compile/run a java project. Here is what I learnt:
javac is used for compiling, java to run an application.
javac takes a .java file, and compiles it into a .class file, that you will run with java. Who needs Eclipse to do that ?!

But real-life project are -a lot- more complicated than that ! You have to put files in packages, classes in another directory, etc...

And you just activated my trap card...
For sure, real project are a lot more complicated ! For example:

~/src/java/eg
├── bin
├── build
│   └── build.xml
├── conf
│   └── server-log4j.properties
├── lib
│   ├── junit-4.11.jar
│   └── log4j-1.2.12.jar
├── src
│   └── com
│       └── irc
│           ├── client
│           │   ├── ClientConnexion.java
│           │   ├── ClientFenetre.java
│           │   ├── Client.java
│           │   └── Client_TEST.java
│           ├── server
│           │   ├── ClientRun.java
│           │   ├── Server.java
│           │   └── Server_TEST.java
│           └── utils
│               ├── Command.java
│               ├── Command_TEST.java
│               ├── Communication.java
│               ├── Communication_TEST.java
│               └── Log.java
└── tags

This is what my project looks like. sources are in src/, classes compiled in bin/. Each source has it's own package.

Let's see how to handle this project, using UNIX as your IDE !

Compilation

It probably is the hardest part. Java is hard to compile properly, so tools like Ant are used in IDEs.

Basicaly, compilation goes like this:

javac -d bin/ -sourcepath src/ -classpath bin/ src/com/irc/utils/Command.java

-d specifies the directory where your classes will go.  
-sourcepath tells javac where to search for source files.  
-classpath is the same as the abode, but for class files.

Do you see it coming ? YES, we will use a Makefile.
Here is mine:

# Locate directories
class_d=bin
lib_d=lib
source_d=src
package_d=com/irc

# Compilation stuff
JAVAC=javac
JFLAGS=-g -d $(class_d) -sourcepath $(source_d) -Xlint:all

classpath:=$(class_d):$(lib_d)/junit-4.11.jar:$(lib_d)/log4j-1.2.12.jar

# If there's already a CLASSPATH, put it on the front
ifneq ($(CLASSPATH),)
        classpath:= $(CLASSPATH):$(classpath)
endif

# Re-export the CLASSPATH.
export CLASSPATH:=$(classpath)

MATCH='.*[^(_TEST)]\.java'

ifdef TEST
    ifeq ($(TEST), all)
        MATCH='.*_TEST\.java'
    else
        MATCH='.*\/$(TEST)\/.*_TEST\.java'
    endif
endif

# Find all the source and convert them to class files
S_SERVER= $(shell find $(source_d)/com/irc/server -regex $(MATCH))
C_SERVER= $(patsubst src/%.java, bin/%.class, $(S_SERVER))
S_CLIENT= $(shell find $(source_d)/com/irc/client -regex $(MATCH))
C_CLIENT= $(patsubst src/%.java, bin/%.class, $(S_CLIENT))
S_UTILS= $(shell find $(source_d)/com/irc/utils -regex $(MATCH))
C_UTILS= $(patsubst src/%.java, bin/%.class, $(S_UTILS))

.SUFFIXES: .java .class
.PHONY: default server client utils clean init all

default: classes

$(class_d)/%.class: $(source_d)/%.java
    @echo "JAVAC $<"
    @$(JAVAC) $(JFLAGS) $<

classes: utils server client $(class_d)

server: $(C_SERVER) utils
client: $(C_CLIENT) utils
utils: $(C_UTILS)

all: init classes

$(class_d):
    mkdir $(class_d)

clean:
    rm -rf $(class_d)/*

It will search the appropriate sources in your sourcepath, and compile them in the associated classpath.
Building the tests appart is done with make TEST=[server|client|utils|all] And it will compile your code only if it has changed (thanks GNU/make !).

It there you need more explaination on this, mail me your questions !

Running

Running your program will be a lot more easier. And you probably know What I'm going to tell you: shell script.

Simple huh ? You just need to know how to run a java program:

java -classpath bin/ com.irc.server.Server

Do I really need to explain what -classpath is ..? On the other hand, "com.irc.server" is the package containing my Server class, and "Server" is the class containing the method main().

So you will have no problems building the correct script that will run your application. It will probably (in its simplest form) look like this:

#!/bin/sh

classpath=bin:lib/log4j-1.2.12.jar
package=com.irc.server

java -cp $classpath $package.Server

Isn't that easy ?

Conclusion

YOU. DON'T. NEED. ECLIPSE. AT ALL.

I know that a lot of people will discard me, telling that This is a pain in the neck to go like this, that you need to know Makefile, and take the time to write them, etc... But these are reusable, and it helps you to know how to manage the whole process ! Furthermore, it can be interesting to (at least) try this method, just to see how it goes. You will be able to use every tool you want, git, vim, emacs, svn, ctags, ...

No needs to get used to the Eclipse interface, and to forget about your favorite editor ! Isn't that promising ?