Skip to content

Instantly share code, notes, and snippets.

@tpraxl
Last active July 9, 2017 14:13
Show Gist options
  • Save tpraxl/76dabfae96c91e5ed2456890ae09851b to your computer and use it in GitHub Desktop.
Save tpraxl/76dabfae96c91e5ed2456890ae09851b to your computer and use it in GitHub Desktop.
Frontend developers guide to working with JEE applications

Background

I'm currently working on frontend stuff for a JEE application.

Some aspects of my usual frontend workflow seemed difficult to achieve in the first place, so I took some time to find out how to get back to my zero-turnaround workflow, even with a foreign setup that seemed to be difficult for that matter.

There seems to be a lack of documentation or written down experience, so I thought, I could at least publish my personal experience / setup. Comments and complement are very welcome.

I noticed that some frontend developers have problems setting up the java environment, so there's a section for this as well.

I'm personally using mainly Ubuntu 14.04 Linux (Mint 17.3), so any setup guides will focus on that.

Windows

If you're a Windows user, this article might be helpful: https://www.twilio.com/blog/2017/01/install-java-8-apache-maven-google-web-toolkit-windows-10.html

Linux, Mac OS, maybe Windows:

On linux, sdkman helps a lot (should also work on Mac OS). See http://sdkman.io/install.html sdkman may work on Windows as well, but I haven't used it there.

curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
sdk install java
sdk install maven

Oracle Java on Linux with sdkman

Notice that you currently (07/2017) only get openJDK when using sdkman.

Oracle Java is currently not available that way, but it's generally not necessary to use Oracle Java.

You can install an Oracle JDK locally and still use sdkman to manage your versions.

To do that, install it locally:

This is an article about installing oracle java on Ubuntu 14.x: https://askubuntu.com/questions/521145/how-to-install-oracle-java-on-ubuntu-14-04

Then (example for Ubuntu 14.x):

sdk install java 8u131-oracle-local /usr/lib/jvm/java-8-oracle
sdk default java 8u131-oracle-local

Install glassfish

Experiences

Glassfish 4 was needed for the project.

The first thing I did was – use docker.

That turned out to be not straightforward:

The basic setup would use eclipse for server management and deployment and it turned out to be too time-consuming to configure it to work with the docker-container. Well at least, it didn't work instantly and I was under some time-pressure, so I decided to just copy everything out of this container, as glassfish basically doesn't need a real installation, just a certain structure and scripts.

The Not-So-Straight-Forward-Way to install glassfish

The following command was straightforward for me, as I already had toyed around with glassfish as a docker-container at that time. Certainly there are better ways to setup glassfish and I appreciate any comments or guides in order to complement this section.

This creates the glassfish directory structure and files in a directory glassfish4 of your host (Ubuntu 14.04):

docker run --rm -v `pwd`/glassfish4:/copy glassfish/server cp -R /glassfish4 /copy

Ports & login

The glassfish default port is 8080. Admin console on 4848. Debug (jdb) 9009.

Standard login to the admin console for the docker container used above would be: admin, glassfish. You'll need this when you're going to configure Eclipse to deploy the application.

Configure eclipse

I received an eclipse maven project from my client – however, maven was not configured to deploy, eclipse would be the tool to do it – so I set up eclipse to be able to deploy the application to glassfish.

Install eclipse on linux

I didn't directly find a ppa way, so I downloaded Eclipse Oxygen from https://www.eclipse.org/downloads/

One or two tips for new users of eclipse

Eclipse uses so-called workspaces. You create a workspace when you start eclipse. Think of it as a (multi-)project folder with specific eclipse settings. Projects need to be imported into the workspace, even if they already exist there.

So I created the workspace at the top-level-location of the existing projects and imported the projects via File->Import…

Auto refresh

Eclipse uses a layer on top of the file system that requires synchronisation of files when they were modified externally (right click->refresh). You should at least try to let eclipse synchronize / refresh automatically. This is convenient if you're modifying your sources in external editors (phpStorm, sublime, …), but it is also important for auto deployment.

Choose Window -> Preferences -> General -> Workspace:

  • Check Build automatically (optional, so that changes will trigger a build and thus an automatic deploy (see below))
  • Check Refresh using native hooks or polling

In my case, this wouldn't work satisfactorily, because there was still a delay of approximately 20 seconds before eclipse noticed the changes, but maybe you have more luck than me.

Automatic deployment / auto publish

In order to let eclipse automatically publish to GlassFish, follow these steps (although this is not necessary if you set up some scripts that will be covered later on).

Choose Window -> Preferences -> Server -> Overlays:

  • Check Automatically republish serers on overlay modifications

Install GlassFishTools

In eclipse: Help -> Marketplace… find and choose GlassFishTools (and choose at least the current documentation along with the first checked item).

Configure GlassFish Runtime Environment in Eclipse

After having restarted eclipse, choose: Windows -> Preferences -> Server -> Runtime Environments -> Add…

Add Glassfish, click Next.

Enter your glassfish location, e.g. glassfish4/glassfish

Enter the location of your JDK, e.g. /home/$USER/.sdkman/candidates/java/8u131-zulu.

Sometimes, it helps if the name matches conventions used by the team you work with. Eclipse will lookup it up using the name. So make sure that this matches your teams conventions. E.g. "GlassFish 4.1".

Then go to Servers -> New…, choose your Runtime and add the respective EAR (Enterprise Application Project). (<- this only applies if you received a JEE Application along with an EAR Project)

Publish the Application manually

Go to Servers (tab at the bottom) -> Right click the entry for your GlassFish Server and choose Publish.

Setup sibling project

In my case, the client wanted to manage the sass / es6 sources and use the bundled artifacts (css/js) while we didn't want to interfere with the existing JEE projects.

So I set up a sibling project:

Using eclipse

In eclipse choose File -> New -> Maven Project.

Check "Create a simple project (skip archetype selection). Leave "Use default Workspace location" checked. -> Next.

Some explanations for the following dialog:

Usually, you're dealing with multiple maven projects. There should be a pom.xml in the top-level-location of your projects (you may not see it in eclipse though, just open it with any text editor). And there should be a pom.xml in every child project.

Have a look at the parent pom.xml and at a child pom.xml.

They often share the same groupId. Sometimes, the groupId will not be present in the child pom, because it is inherited. But you will usually see a parent section in the child pom that references the parent pom's groupId, artifactId and version.

You should enter this groupId in the dialog. As for the artifactId, talk to the team or assign it a perceivable name. The version depends on the preferences of your team: Maybe all projects have the same version number. Then you should enter this one. Maybe each project has it's own versioning. Then you may enter 0.1.0-SNAPSHOT or similar.

The packaging should be pom as you are not about to generate a jar or war from this project.

Fill out the parent project's groupId, artifactId and version as given in the top-level location pom.xml.

Click Finish.

Make sure that the top-level pom.xml contains your project in the <module> section.

Setup frontend-maven-plugin to be able to build your sources with nodejs as part of the maven build process

General setup

See https://github.com/eirslett/frontend-maven-plugin for background information on this plugin.

The plugin will install a local version of nodejs if necessary, run npm install and your build if configured correctly when the project is built (mvn install).

Modify the project->build->plugins section (or create this xml structure), so that the pom looks similar to this:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <!-- substitute these values -->
    <groupId>com.your.projects.groupId</groupId>
    <artifactId>parent-project-artifactId</artifactId>
    <version>your-parent-version-SNAPSHOT</version>
  </parent>
  <!-- substitute these values -->
  <artifactId>your-projects-artifactId</artifactId>
  <packaging>pom</packaging>
  <name>Your-name-of-choice</name>
  <build>
	  <plugins>
		  <plugin>
		  	<groupId>com.github.eirslett</groupId>
	        <artifactId>frontend-maven-plugin</artifactId>
	        <version>1.4</version>
	        <executions>
	
	          <execution>
	            <id>install-node-and-npm</id>
	            <goals>
	              <goal>install-node-and-npm</goal>
	            </goals>
	            <configuration>
	              <!-- See https://nodejs.org/en/download/ for latest node and npm (lts) versions -->
	              <nodeVersion>v6.11.0</nodeVersion>
	              <npmVersion>3.10.10</npmVersion>
	            </configuration>
	          </execution>
	
	          <execution>
	            <id>npm-install</id>
	            <goals>
	              <goal>npm</goal>
	            </goals>
	            <!-- Optional configuration which provides for running any npm command -->
	            <configuration>
	              <arguments>install</arguments>
	            </configuration>
	          </execution>
	
	          <execution>
	            <id>npm-run-build</id>
	            <goals>
	              <goal>npm</goal>
	            </goals>
	            <configuration>
	              <arguments>run build</arguments>
	            </configuration>
			  </execution>
			  
		  	</executions>
		  </plugin>
	  </plugins>
  </build>
</project>

Using other build tools

Notice that this setup only covers the normal npm run build. I integrated my build into the package.json according script. If you need other commands, see https://github.com/eirslett/frontend-maven-plugin .

Provide a package.json

Now, you're finally approaching well-known teritory. Provide a package.json in your subproject root. Make sure that it defines a build script.

I'm using laravel-mix (convenience layer on top of webpack), which looks like this. Don't simply copy it. There are old versions referenced and you likely want to adapt it to your own needs.

{
  "private": true,
  "scripts": {
    "dev": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch-poll": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --watch-poll --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
    "build": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
  },
  "devDependencies": {
    "axios": "^0.15.3",
    "babel-polyfill": "^6.23.0",
    "cross-env": "^3.2.4",
    "font-awesome": "^4.7.0",
    "jquery": "^3.1.0",
    "laravel-mix": "^0.12.1",
    "lodash": "^4.16.2",
    "vue": "^2.2.6",
    "webpack": "^2.6.1"
  },
  "dependencies": {},
  "name": "my-name",
  "version": "1.0.0",
  "main": "index.js",
  "author": "",
  "license": "MY-LICENSE",
  "description": ""
}

provide helper scripts

It might come in handy to use the local npm version during development. To do so, you should copy the following helper scripts and paste them into your subproject root:

Make the sibling project build to the JEE Project's resources directory

Just configure your build tool (gulp, webpack, laravel-mix) to produce the output where the JEE Project needs it. The JEE Project should be a sibling, so this should be a path like ../jee-project/src/main/webapp/resources/style/app.css or similar. If this doesn't work for you, see below for a watch-script on linux and adjust it to your needs (in that case, it should watch for changes to your regular build directory (e.g. dist, public,…) and copy the results over to the JEE Project.

Zero-turnaround publishing to glassfish and browser-sync

If you followed my advices until here (and if you're in luck with eclipse auto refresh and auto publish), your environment should now detect changes to your source files (e.g. sass), build them automatically (css) and deploy the changes to GlassFish.

However, I was not so lucky, so I wrote a little helper (and added browser-sync while I was on the way).

The more professional way would likely involve some of glassfish's scripts to deploy resources to it. However, I found it sufficient to just copy files into the directory structure of deployed applications in glassfish. Just make sure to deploy your application once before calling the script.

Notice that this makes me independent of eclipse. I just used it for the first deployment of the application. To be able to start glassfish without eclipse, there's another little helper:

#!/bin/sh
# run-glassfish.sh
# start glassfish server
sh glassfish4/bin/asadmin start-domain --debug -v

The following script, sync.sh, requires some external tools (nodejs / browser-sync and inotify-tools – see comments).

Also, see comments for values to be substituted by you:

#!/bin/sh
# sync.sh
# Substitute with path to JEE resources folder, e.g. jee-web/src/main/webapp/resources
WATCH=path-to-your-jee-webapp-resources-folder-without-trailing-slash
SRC=$WATCH
# Substitute with the path to the deployed resources on your glassfish-server. 
# E.g. glassfish4/glassfish/domains/domain1/eclipseApps/jee-ear-project/jee-web_war/resources
TARGET=path-to-your-deployed-resources-without-trailing-slash

# start browser sync in background
# it proxies localhost:8080 (glassfish) and will delay refreshing for 1.5 secs after file modification
# 
# read the script output to know where to point your browser to
# 
# Note: browser-sync required -> npm install -g browser-sync 
browser-sync start --proxy "localhost:8080" --reload-delay 1500 --files $TARGET &

# watch files for change and hot-deploy them to glassfish
# 
# Note: inotify-tools are required -> apt-get install inotify-tools
while inotifywait -r -e modify $WATCH; do
	cp -R $SRC/style $TARGET/
done

# kill all subprocesses (browser-sync) when this script ends
kill -- -$$

Both scripts are located in the top-level folder of the project (one level above my subproject)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment