My Thoughts on Spring vs. Java EE6

The relationship between Spring and Java EE has aspects of real human drama. There is the powerful giant that refused innovation for years (J2EE). There is the contrarian crusader that wanted to set things right (Spring). Development shops abandoned J2EE ship in droves and took shelter with Spring. Then the giant woke up and changed its ways (Java EE6). And with that response, the world became much less black and white. What is the role of Spring now? How will it react to the new ground realities?

Answering these questions is not easy. Any kind of blanket statement about Spring or Java EE will be a folly. They are both collections of different frameworks and technologies. A far better conversation will involve analyzing these frameworks and technologies separately. This will give one a better picture about where Java EE 6 has done well and where Spring is still beating it.

Before I delve into the technical details, I must address the issue of human emotion, especially in relation to trust. It is a fact that people have been burnt by Java’s lack of innovation in the server space for far too long. Spring became a savior for them. People will not forget that so easily. Java EE 6 implementations (JBoss, WebSphere etc.) are more than a year old now. Spring continues to be very much in the hearts and minds of the developers. I make that statement based on two observations:

  1. Have a look at the job postings in Monster or Dice. A very large proportion of Java jobs require Spring experience.
  2. There has been a lot of innovation lately in the cloud space. None of the major Platform as a Service (PaaS) providers, like Amazon Beanstalk and Google App Engine, support Java EE 6. They all support Spring effortlessly. The fact that Spring works in the highly restrictive Google App Engine environment is nothing less than stunning.

The continued dominance of Spring, as I conclude by the end of this article, is largely due to emotional inertia and some technical advantages.

Let’s now have a look at the technical aspects of Spring and Java EE 6. I will limit this article to the areas where I can claim some expertise and experience. Even in those areas, I can not claim absolute knowledge. These are then, my personal opinions. They are open to correction based on your feedback and my own learning.

Dependency Injection (DI)

Context and Dependency Injection (CDI) feature of Java EE 6 has been very well put together. It is easy to learn and use. I think, for most common tasks, CDI is just as good a DI tool as Spring.

A down side of CDI is that it needs a full Java EE container. Technically, CDI will not work in plain Tomcat. Although, others have found simple workarounds to getting Weld working in Tomcat. Last time I checked, Weld is still not supported by Google App Engine.

Web Model View Controller (MVC) Framework

JavaServer Faces (JSF) is the official out-of-the box MVC framework in Java EE. JSF 2.0 has been a major improvement. Unfortunately, JSF is still a big mess. It is a fine framework for building a 90’s web site. But, a pain in the neck for building a modern HTML5 web site with complex Ajax interactions and SEO friendly URL. I will almost always suggest Spring MVC framework over JSF for most projects.

Time has come to completely rethink Java’s MVC strategy. My own Pink framework leverages all that is great about Java EE 6, like CDI and Bean Validation (JSR 303). It practically matches Spring MVC feature by feature. We need something similar out of the box from Java EE.

SOAP and RESTful Web Service

Java has done a tremendous job with JAX-WS and JAX-RS. I have used both extensively. Just like CDI, they are very well put together, easy to learn and use. At the same time, they support proper programming practices like contract first design.

I had a brief look at Spring-WS. I really fail to see why Spring even bothered to create this module. For all practical purposes, I will recommend using JAX-RS and JAX-WS.

Component Model

The preferred component model for Java EE is EJB. In the past, EJB had been cumbersome and pain to work with. A lot has changed since then. In Java EE 6, you can:

  1. Create EJBs right inside a web module. There is no need for a separate EJB module.
  2. Define local EJBs without any business interface.
  3. Lifecycle methods are completely optional.

In other words, EJBs are now just as easy to develop as Spring components. Spring documentation continues to say things like “The negatives of EJB in general are so great that this is not an attractive proposition”. Really? I can’t really agree to that. Neither can I agree that Spring’s transaction management is any better or worse than EJBs.

Runtime Environment

This is an area where Spring enjoys an undisputed advantage. Spring, in all it’s glory, will work in plain Tomcat, Google App Engine and Amazon Beanstalk. This includes, DI, JPA, transaction (local only) and the whole deal. Tomcat, GAE and the likes do not care much for Java EE certification. They live happily in a symbiotic relationship with Spring.

Unlike Spring, different Java EE specifications are implemented separately. For example, CDI comes from Weld, Bean Validation comes from Apache BVal, JPA from Open JPA and so on. Getting these to work together is a Herculean task. In fact, that is what the fine folks at TomEE are trying to do. It has taken a number of developers almost a year to put all the pieces together on top of Tomcat to create a full Java EE 6 web profile.

Summary and Conclusions

Spring has made tremendous contributions to the development community. One indirect contribution is the competition that it gave to Java EE. Java finally woke up and responded with Java EE 6. Unfortunately, one of the most critical pieces of Java EE – the MVC framework – remains deeply flawed. In all honesty, I will always steer my clients to frameworks like Spring MVC, Struts 2 and Stripes. The second advantage of Spring is its support for almost any web container, including the awkward ones like GAE. These two advantages will continue to cause Spring’s dominance in development projects.

Out of the two main disadvantages of Java EE 6, JSF 2.0 is more critical. Java badly needs a modern MVC framework. Startup companies avoid Java like plague. Enterprises prefer Spring MVC (based on what I have seen in the job listing sites).  If this gap is somehow filled, either from Java EE (which is highly unlikely at this time) or from third party (like my own Pink framework or something like Struts 2), then Java EE will pose a formidable challenge to Spring.

Create a Web Site for Your GitHub Repository

You can host a web site with GitHub that goes with your repository. This is a great way to show documentation, tutorials and so on for your project. GitHub gives you a web based tool to create a one page site. You can build a more complex web site from there. This post will show you how to do that.

Create the One Page Site

Log into Git Hub. Go to your repository’s page. Click Admin link. From the GitHub Pages section, click Automatic Page Generator. Feel free to enter some initial text for the page. Then click Continue to Layouts at the bottom. Choose a layout and click Publish. It takes about 10 minutes for the changes to take place. After that, you should be able to see your site. For example, if my repository is called MyProject, the URL will be http://bibhas2.github.com/MyProject/.

GitHub will create the necessary HTML and other files. They will be committed within the repository in the gh-pages branch. To manually maintain new pages and other files, you will need to work with that branch.

Manually Manage the Site

First, in your workstation, clone the gh-pages branch of the repository. For example, if your repository is called “MyProject”, run this command to clone it:

git clone https://github.com/bibhas2/MyProject.git -b gh-pages

Now, if you go inside the repository folder, you will see the web site files.

drwxrwxr-x 2 wasadmin wasadmin 4096 Nov 23 13:27 images
-rw-rw-r-- 1 wasadmin wasadmin 9176 Nov 23 13:30 index.html
drwxrwxr-x 2 wasadmin wasadmin 4096 Nov 23 13:27 javascripts
-rw-rw-r-- 1 wasadmin wasadmin 7527 Nov 23 13:27 params.json
drwxrwxr-x 2 wasadmin wasadmin 4096 Nov 23 13:27 stylesheets

Edit the files as you see fit. Then push the changes out to update the site.

git commit -a
git push origin

Refresh your sites web page to see the changes.

Pushing Existing Repository to GitHub

Let’s say that you have a local Git repo that you have been using to manage your code for a while. Now, you wish to publish it to  GitHub so others can look at it and participate in development. How will you do that?

Well, the key to pushing to any remote repo for the first time is to make sure that the remote repo is completely empty. Normally, you will use “git init –bare” to create a bare/empty repo on the remote server. In GitHub, you use the web GUI to create a repo. There, make sure that you do not choose Initialize this repository with a README checkbox. This will create a bare repo in GitHub.

After the repo is created in GitHub, run these commands from your local Git repository. Let’s say that the URL for the newly created GitHub repo is “https://github.com/bobby/MyRepo.git”.

git remote add MyGitHub https://github.com/bobby/MyRepo.git
git push MyGitHub master

Then, enter your GitHub user ID and password.

So, the trick is not to create the README file when you create the repository in GitHub. Otherwise, the repository will not be bare and when you try to do a push, you will get an error message “Updates were rejected because the tip of your current branch is behind”.

Git Tutorial for Beginners Part II

In Part I, I tried to introduce Git to non-believers who have their brains formatted by CVS. We learned to create a repository and commit files to it. Part II will be very short. We will learn to look at the history of changes made to a file and learn to revive an old version of the file.

Let’s say, that you have a file called test.c. This file has been committed several times in the past. You can look at the history of changes by running this command.

git log test.c

This will display something like this.

commit 9faa6e6d4df82766de1ecc63ff5e79463e21c7cb
Author: Bibhas Bhattacharya <bibhas@example.com>
Date: Wed Aug 15 10:03:29 2012 -0400
Comments2

commit f8648963ac296d974dedd5530a56a024c495219c
Author: Bibhas Bhattacharya <bibhas@example.com>
Date: Wed Aug 15 10:01:43 2012 -0400

Comments1

The date and author of every commit made for the file is displayed. In CVS, each commit creates a new version number. In Git, you get a unique key for the commit. This is shown in bold face above. Git generates the key by using SHA-1 hash of the Git tree (something that closely resembles the files and directories as they existed at the time of the commit).

So, anyway, the important thing is that there is no CVS like version number. Every version has a unique key.

Now, let’s say that you made a terrible mistake to the file. Perhaps your cat went in the middle of the night and typed in gibberish to it and saved it. Now what? Well, first we need to find out what has changed since a specific commit. For that, run this command:

git diff 9faa6e6d4df82766de1ecc63ff5e79463e21c7cb test.c

The hash value of the commit you are trying to compare with goes into the command.

This will print out a terrible output that only Martians can understand.

index a4b000a..01dfe10 100644
--- a/src/test.c
+++ b/src/test.c
@@ -1,2 +1,2 @@
-New line
-Line 2
+New line was here
+Only a memory 3

Fortunately, git works with many excellent visual diff programs. Most installations probably have vimdiff configured by default. To view the difference in a graphical tool, run this command:

git difftool 9faa6e6d4df82766de1ecc63ff5e79463e21c7cb test.c

To configure a different diff tool, read this article. Right about now, I am starting to miss my Eclipse diff view. Oh, how many times has it come to my aid in times of major distress!

Anyway, getting back to the mischief caused by your cat. We now have to fix the problem. The diff may show the source of the error and you may be able to manually fix the problem. If you must start from scratch, just checkout the older version.

git checkout 9faa6e6d4df82766de1ecc63ff5e79463e21c7cb test.c

This will completely replace the file with the older version.

Setting up a Git Server in Linux

Hello all. I needed to setup a Git server for my team and didn’t want to commit to a paid GitHub account yet. So, I set out to setup a Git server of my own. Instructions are sketchy at best. But, I think I got it to work.

I am using CentOS 5.0 i386.

First, we need to configure Yum to use the RedHat extended Linux repository. For i386 system, run this command:

rpm -Uhv http://apt.sw.be/redhat/el5/en/i386/rpmforge/RPMS/
    rpmforge-release-0.3.6-1.el5.rf.i386.rpm

If you are using a 64bit OS, run this instead:

rpm -Uhv http://apt.sw.be/redhat/el5/en/x86_64/rpmforge/RPMS/
    rpmforge-release-0.3.6-1.el5.rf.x86_64.rpm

Then, install Git by running these commands.

yum -y install git
yum -y install git-daemon

Now, we are all set to start the server. First, create a folder that will be the root of all repositories. Let’s say /root/git.

Start Git daemon as follows:

git daemon --reuseaddr --base-path=/root/git --export-all --verbose 
    --enable=receive-pack &

That’s it. If you are running a firewall, drill a hole in port 9418.

Let’s quickly test things out.

We will first create a repository in the server. Recall, we used /root/git as the root of all repositories in the server. So go there and create a folder for a repository.

cd /root/git
mkdir ProjectA
cd ProjectA
git init --bare

OK, now we have a bare repository on the server called “ProjectA”.

Now, go to a client machine. Run these commands to push to the remote repository ProjectA.

mkdir ProjectA
git init
touch README.txt
git add .
git commit -m "Project creation"
git push git://SERVER_IP_OR_HOSTNAME/ProjectA master

This should work and get you in business.

Git Tutorial for Beginners Part I

I must admit, I am one of those who had their brains formatted by CVS. It was darn difficult to understand Git and its benefits. I figure there are many like me out there. This is why I decided to write a Git tutorial series from my view point. Also, I apply Git to a smaller scale project than say, Linux kernel with a massive number of developers.

My knowledge of Git is nowhere near being at an expert level. I’m sure I will say something that is stupid. So please bear this in mind in your comments. Please help me make this series better.

I found a few things really helpful when learning about Git:

  • I found this book on Git very helpful. It’s completely free.
  • Whether you are following this tutorial or reading the book above, always actually do the steps. Just reading about Git will get your brains confused really quickly. Actually doing the steps will help you a lot.
  • The best way to learn about Git is to use the command line tools. IDEs like Xcode and Eclipse have some level of Git support. But, as a beginner, they really messed me up.

In Part I, we will focus on code committing. We will get to working with branches in future parts.

Please make sure that you have a working Git command line system before proceeding. The book mentioned above has clear steps on installation in Linux, Windows and Mac (I am using Mac to write these articles).

What is a Repository?

In CVS there is only one repository – the one that sits in the central server. Every developer has a working copy of the files in a local folder.

In Git, typically, each developer has a local repository. This is where code is committed frequently. Since this is a local repo, you don’t have to be super careful that the code works or even compiles:-). Basically, you are backing your work up periodically. In case of a bad mistake, you can always get things back from the local repo.

Once you are happy with the code, you can push the changes to a central repository. When pushing your code to the central repo, you can choose to include the history of every local commits. Or, better yet, you can compress all local commits into a single commit. This is better. Because, other developers don’t need to know about every little local commits you have done. We will get to this later.

Creating a Local Repository

There are two ways you can create a local repository:

  1. Create a brand new repository for a new project. This is usually done only once in the life of a project.
  2. For existing projects, create a clone of a remote repository in your local hard drive.

Let’s first learn to create a brand new local repository. Xcode and Eclipse provides ways to create a new local repo for any project. But, as I said, let’s not use the IDEs for this yet.

Create a folder structure for your project. If you are using Xcode or Eclipse, just create the project using the IDE tools.

Open a command prompt window and go to the root folder of the project. (Xcode creates many folders with similar sounding names. The root folder contains the PROJECT.xcodeproj folder. So, yeah, it’s really the root folder.)

Run this command to create a new local repository for the project.

git init

The repository is physically created in the .git folder within the root. If you regularly backup your hard drive, don’t forget to include that folder.

Now, let’s see how to create a local repo by cloning a remote one. This is something you need to do to contribute code to a project that already exists.

Using the command prompt, go to any folder. It should not be initialized using git init (which is only used to create a brand new repo). Then run the git clone command with the URL to the remote repo. For example, try this:

git clone git://github.com/bibhas2/ThreadControl.git

This will create a folder for the project within where you are right now. This folder will have the repository in it (in .git).

Committing Files

Commit is a multi step process. New or modified files are first added to a list of files to be committed. This is called staging. Then you do the commit. Also, as I said, commits are first done to a local repo. Changes are finally pushed to a remote repo.

This type of multi-stage commit process really helps developers experiment freely.

Let’s get started. Create a bunch of files in your project’s folder. If you are using Xcode or Eclipse, this is already done for you.

From the command prompt, use the git add command to add files to the staging area (list of files ready for commit). For example, running this command from the root folder will add all modified files to the staging area:

git add .

Alternatively, you can selectively add files or folders to commit list. If you specify a folder, all subfolders are recursively traversed and all files are added to the staging area.

git add file.c
git add src/

Note: Every time you modify a file, you will need to schedule it for commit using git add. This is nothing like the cvs add command. With git add, you are not adding a file to the repository. You are adding it to a list of files ready for commit.

If you have deleted a file, you can schedule that change for commit using git rm command.

git rm test.c

Before you go ahead and commit, you should probably see what exactly will be committed. This can be done using the git status command. A file can be in any one of these states:

  1. A file was created, modified or deleted and has been staged for commit. Only these changes will be committed.
  2. A file was modified or deleted but has not been staged for commit. These changes will not be committed.
  3. A file has been created but has not been staged for commit. Git is not even tracking this file in anyway.

Let’s see an example git status output. You can run the command from any folder within the project. The output will be the same.

git status

A sample output will be:

# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# deleted: test.c
#
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: ../README
# modified: another.c
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# new.c

The file test.c was deleted and was scheduled for commit (using git rm). Only this change will be committed. Files README and another.c have been modified but have not been scheduled for commit. The file new.c was created but never scheduled for commit. Git is not tracking this file in any way.

Finally, to commit the changes, use the git commit command.

git commit
git commit -m "A commit message"

Carefully staging each modified file may be tedious. Especially, if you have made mass changes. In that case, do an auto staging using the -a switch.

git commit -a

This will automatically add all modified files to the staging area and remove deleted files prior to doing a commit.

Things to Consider

What gets staged is not so much a file but changes to a file. Consider the scenario:

  1. You modify a file.
  2. Stage the file for commit.
  3. Make more changes to the file.
  4. Commit the file. This will only commit the contents of the file as it was when it was staged.

Also, in CVS, a single repository stores many Eclipse or Xcode projects. They are called modules. You checkout individual modules as needed. In Git, each project has its own repository. If you have several projects that are closely tied together, it may be cumbersome to work with multiple different repositories. In that case, you can create a super-repository that will contain individual Xcode or Eclipse projects as subfolders. For example, let’s say that we have a Eclipse workspace with these folders:

.metadata – This is used by Eclipse. There is no need to store it in Git repo.
ProjectA – An Eclipse project
ProjectB – Another Eclipse project

You can create a single Git repo for the whole workspace. From the workspace folder, run:

git init
git add ProjectA
git add ProjectB

In addition, create a .gitignore file in the workspace folder to exclude the .metadata folder.

.metadata/   #Exclude this folder
*.class      #Exclude Java classes