Last week I was tasked with developing a quick prototype that used AngularJS for its client and Spring MVC for its server. A colleague developed the same application using Backbone.js and Spring MVC. At first, I considered using my boot-ionic project as a starting point. Then I realized I didn't need to develop a native mobile app, but rather a responsive web app.
My colleague mentioned he was going to use RESThub as his starting point, so I figured I'd use JHipster as mine. We allocated a day to get our environments setup with the tools we needed, then timeboxed our first feature spike to four hours.
My first experience with JHipster failed the 10-minute test. I spent a lot of time flailing about with various "npm" and "yo" commands, getting permissions issues along the way. After getting thinks to work with some sudo action, I figured I'd try its Docker development environment. This experience was no better.
JHipster seems like a nice project, so I figured I'd try to find the causes of my issues. This article is designed to save you the pain I had. If you'd rather just see the steps to get up and running quickly, skip to the summary.
sudo rm -rf /usr/local/lib/node_modules sudo rm -rf /usr/local/include/node sudo rm /usr/local/bin/node sudo rm -rf /usr/local/bin/npm sudo rm /usr/local/share/man/man1/node.1 sudo rm -rf /usr/local/lib/dtrace/node.d sudo rm -rf ~/.npm
Next, I ran "brew doctor" to make sure Homebrew was still happy. It told me some things were broken:
$ brew doctor Warning: Broken symlinks were found. Remove them with `brew prune`: /usr/local/bin/yo /usr/local/bin/ionic /usr/local/bin/grunt /usr/local/bin/bower
brew update && brew prune, followed by
brew install nvm. Next, I added the following to my ~/.profile:
source $(brew --prefix nvm)/nvm.sh
To install the latest version of node, I ran the commands below and set the latest version as the default:
nvm ls-remote nvm install v0.11.13 nvm alias default v0.11.13
Once I had a fresh version of Node.js, I was able to run JHipster's local installation instructions.
npm install -g yo npm install -g generator-jhipster
Then I created my project:
I was disappointed to find this created all the project files in my current directory, rather than in a subdirectory. I'd recommend you do the following instead:
mkdir ~/projectname && cd ~/projectname && yo jhipster
Before creating your project, JHipster asks you a number of questions. To see what they are, see its documentation on creating an application. Two things to be aware of:
- Hot reloading Java code doesn't work well (yet) with Java 8
- Its OAuth2 implementation doesn't work with WebSockets
In other words, I'd recommend using Java 7 + (cookie-based authentication with websockets) or (oauth2 authentication w/o websockets).
After creating my project, I was able to run it using "mvn spring-boot:run" and view it at http://localhost:8080. To get hot-reloading for the client, I ran "grunt server" and opened my browser to http://localhost:9000.
I had no luck getting the Docker instructions to work initially. I spent a couple hours on it, then gave up. A couple of days ago, I decided to give it another good ol' college-try. To make sure I figured out everything from scratch, I started by removing Docker.
I re-installed Docker and pulled the JHipster image using the following:
sudo docker pull jdubois/jhipster-docker
The error I got from this was the following:
2014/09/05 19:43:38 Post http:///var/run/docker.sock/images/create?fromImage=jdubois%2Fjhipster-docker&tag=: dial unix /var/run/docker.sock: no such file or directory
After doing some research, I learned I needed to run
boot2docker init first. Next I ran
boot2docker up to start the Docker daemon. Then I copied/pasted "export DOCKER_HOST=tcp://192.168.59.103:2375" into my console and tried to run
docker pull again.
It failed with the same error. The solution was simpler than you might think: don't use
$ docker pull jdubois/jhipster-docker Pulling repository jdubois/jhipster-docker 01bdc74025db: Pulling dependent layers 511136ea3c5a: Download complete ...
The next command that JHipster's documentation recommends is to run the Docker image, forward ports and share folders. When you run it, the terminal seems to hang and trying to ssh into it doesn't work. Others have recently reported a similar issue. I discovered the hanging is caused by a missing "-d" parameter and ssh doesn't work because you need to add a portmap to the VM to expose the port to your host. You can fix this by running the following:
boot2docker down VBoxManage modifyvm "boot2docker-vm" --natpf1 "containerssh,tcp,,4022,,4022" VBoxManage modifyvm "boot2docker-vm" --natpf1 "containertomcat,tcp,,8080,,8080" VBoxManage modifyvm "boot2docker-vm" --natpf1 "containergruntserver,tcp,,9000,,9000" VBoxManage modifyvm "boot2docker-vm" --natpf1 "containergruntreload,tcp,,35729,,35729" boot2docker start
After making these changes, I was able to start the image and ssh into it.
docker run -d -v ~/jhipster:/jhipster -p 8080:8080 -p 9000:9000 -p 35729:35729 -p 4022:22 -t jdubois/jhipster-docker ssh -p 4022 jhipster@localhost
I tried creating a new project within the VM (
cd /jhipster && yo jhipster), but it failed with the following error:
/usr/lib/node_modules/generator-jhipster/node_modules/yeoman-generator/node_modules/mkdirp/index.js:89 throw err0; ^ Error: EACCES, permission denied '/jhipster/src'
The fix was giving the "jhipster" user ownership of the directory.
sudo chown jhipster /jhipster
After doing this, I was able to generate an app and run it using "mvn spring-boot:run" and access it from my Mac at http://localhost:8080. I was also able to run "grunt server" and see it at http://localhost:9000
However, I was puzzled to see that there was nothing in my ~/jhipster directory. After doing some searching, I found that the docker run -v /host/path:/container/path doesn't work on OS X.
I shutdown my docker container by running "docker ps", grabbing the first two characters of the id and then running:
docker stop [2chars]
I started the JHipster container without the -v parameter, used "docker ps" to find its name (backstabbing_galileo in this case), then used that to add samba support.
docker run -d -p 8080:8080 -p 9000:9000 -p 35729:35729 -p 4022:22 -t jdubois/jhipster-docker docker run --rm -v /usr/local/bin/docker:/docker -v /var/run/docker.sock:/docker.sock svendowideit/samba backstabbing_galileo
Then I was able to connect using Finder > Go > Connect to Server, using the following for the server address:
To make this volume appear in my regular development area, I created a symlink:
ln -s /Volumes/jhipster ~/dev/jhipster
After doing this, all the files were marked as read-only. To fix, I ran "chmod -R 777 ." in the directory on the server. I noticed that this also worked if I ran it from my Mac's terminal, but it took quite a while to traverse all the files. I noticed a similar delay when loading the project into IntelliJ.
Phew! That's a lot of information that can be condensed down into four JHipster + Docker on OS X tips.
- Make sure your npm installation doesn't require sudo rights. If it does, reinstall using nvm.
- Add portmaps to your VM to expose ports 4022, 8080, 9000 and 35729 to your host.
- Change ownership on the /jhipster in the Docker image: sudo chown jhipster /jhipster.
- Use svendowideit/samba to share your VM's directories with OS X.