Any code changes that are made in an eclipse environment with auto-build enabled will automatically publish content to the loose application, meaning no server restarts should be required between code changes.
Several of the backend entities need to be represtented as JSON data so they can be sent to the frontend via websocket, these include objects like `GameBoard`, `Obstacle`, and `Player`. Using POJOs and the occasional `@JsonbTransient` annotation, we used JSON-B to transform Java objects to JSON data.
```java
public class GameBoard {
@JsonbTransient
public final short[][] board = new short[BOARD_SIZE][BOARD_SIZE];
public final Set<Obstacle> obstacles = new HashSet<>();
public final Set<MovingObstacle> movingObstacles = new HashSet<>();
public final Set<Player> players = new HashSet<>();
// ...
}
```
By default, JSON-B will expose any `public` members as wel as public `getXXX()`, this includes other objects such as the `Set<Player> players` field. The resulting class gets serialized into something like this:
Each of the 3 backend microservices in Liberty Bikes (auth, game, and player) exposed a REST API. In most cases the frontend would call the backend REST services, but sometimes the backend services had to call each other.
For example, when a game is over, the game service makes REST calls to the player service to update the player statistics. To accomplish this, the game-service simply defines a POJI (plain old Java Interface) that represents the player-service API it cares about, including the data model:
The only non-Java part about MP Rest Client is the need to specify the base path to the service via JVM option. This is easy enough to do in the build scripting, and easily overridable for cloud environments:
Executors from Java SE are very easy to use, and the "Managed" equivalent Executors in EE Concurrency lets you use all of the SE functionality with the added benefit of running the work on threads that are A) managed by the application server and B) have the proper thread context metadata to perform "EE type" operations such as CDI injections and JNDI lookups.
```java
System.out.println("Scheduling round id=" + roundId + " for deletion in 5 minutes");
Liberty Bikes can be built and run with a single command and no prereqs thanks to Gradle and the Liberty Gradle Plugin! With these build tools we can easily control a bunch of things:
- Downloading and "installing" Liberty
- Managing build and runtime dependencies (i.e. compile-time classpath and jars that get packaged inside the WAR applications)
- Starting and stopping one or more Liberty servers
To get the Liberty gradle plugin, we add this dependency:
Or, if we want to use a Beta image instead of an official GA'd image, we specify a URL in the `liberty.install` task instead of as a runtime dependency:
And lastly, we added some convenience Gradle tasks to make our life a bit easier (shorter names for less typing, always run unit tests before starting the server, and always stop the server before trying to start it!).
```groovy
libertyStart.dependsOn 'libertyStop', 'test'
task start { dependsOn 'libertyStart' }
task stop { dependsOn 'libertyStop' }
```
## Continuous Delivery
Early on we set up a build pipeline on IBM Cloud that we pointed at this GitHub repository. Every time a new commit is merged into the `master` branch, the pipeline kicks off a new build and redeploys all of the services. The average time from pressing merge on a PR to having the changes live on libertbikes.mybluemix.net is around 20 minutes.
The pipeline UI looks like this in our dashboard:
![Image of build pipeline](https://user-images.githubusercontent.com/5427967/40152561-41fa1c46-594b-11e8-98b1-3f9f0f0c6472.PNG)
The pipeline consists of 2 stages: Build and Deploy.
The build stage simply points at the GitHub repository URL, and has a little bit of shell scripting where we define how to build the repo:
For the deployment stage, each microservice gets its own step in the stage. We could also split the microservices into separate stages (or even different pipelines) if we didn't always want to redeploy all microservices. Like the build stage, the deploy stage has a little bit of shell scripting at each step:
```bash
#!/bin/bash
# Unzip the archive we receive as build input
cd game-service/build/libs
unzip game-service.zip -d game-service
# Set some Cloud Foundry env vars (use the latest WAS Liberty beta)