Wednesday, April 27, 2016

JHipster JDL Notes

JDL.  JDL stands for JHipster Domain Language and is a shorthand notation for describing entities and relationships for the jhipster-uml to consume when generating the domain portion of you JHipster code.  My current JHipster learning project quickly evolved to using this format after a few painful sessions with the question and answer approach of the yoeman jhipster:entity sub generator.  The jdl format is pretty concise and allows you to quickly specify the attributes you need to define entities: properties, types, constraints and relationships.

First Issue Encountered.  Once I had my entities defined in JDL and had the generator working to the point where I had working CRUD for all my entities, I started playing with the functionality.   The first thing I noticed was that all of the entities that had relationships to others (let's say children entities) would always represent the child as the Primary Key ID value of the object.  To illustrate I'll use the example of an Employee - Department relationship where an department has many employees.  When listing the employee, JHipster would show all of the attributes of the employee (name, position, years employed) and then show the numeric id (Primary Key) of the department.  Not a very good user experience.  Of course what I wanted was the department name, both in the listings of the employee and as a drop down selection when editing a single employee.  

First Issue Solved. It makes sense that JHipster used the department id as the data showing the relationship.  After all, I did not tell it WHICH piece of data in the department object would be meaningful (and unique) to the user.  Thankfully the the JDL has a nice facility to not only indicate the relationship between entities, but also indicate the field which would be meaningful to the user, and thus be used to represent the relationship on the parent object when used in the UI. My original relationship section of my JDL looked like this:

relationship ManyToOne {
    Employee {worksInDept} to Department
}
This defines that there are many employees in a department and that the employee entity will contain a property named worksInDept that will be the child department object.  When the relationship is defined like this, JHipster simply defaults to using the department id in representing department in any employee UI areas.  In order to tell JHipster that the property on the department object to be used, I had to make the following change:

relationship ManyToOne {
    Employee {worksInDept(deptName)} to Department
}

Note the add of the deptName property.  Not sure what this construct is actually called in JDL.  It shows up in one of their examples but is not documented in the relationship declaration definition:

relationship (OneToMany | ManyToOne | OneToOne | ManyToMany) {
  <from entity>[{<relationship name>}] to <to entity>[{<relationship name>}]
}

Second Issue Encountered. So the addition of the unnamed attribute in JDL seemed to have solved my first issue. The generated code included additional references in the EmployeeDTO to the new deptName property called worksInDeptDeptName and appeared to use it through to the angular display of employees (lists, edit, etc). However when I ran the app, the mapper did not map the new field on the DTO. It left it null. The EmployeeMapper clearly had a mapping annotation to pull the from the related worksInDept object and put it in worksInDeptDeptName, but it wasn't doing it at run time.

Second Issue Solved. My first thought was that the mapping library was broken. My second thought was that there is no way that wouldn't get fixed before I see it in release. I then started looking at the MapStruct lib and learned that it does its mapping magic by generating code for the mappers at compile time. I happened to be running my code in Intellij from its Spring Boot run configuration and I pretty quickly guessed that it was bypassing the code generation that the Gradle build was doing. I ran the Gradle build and the mappers worked. No more nulls and I get the user friendly department name throughout the Employee UI facilities.

Next Up.  One of my big frustrations with code generation approaches is how to add code and not break the upgrade path.  When a new JHipster version comes out, I have a laborious set of tasks to restore my custom adds (homepage, ssl, etc) after re-running the code generation.  I'll start to think about how to deal with this and write up my findings as I arrive at them.

Tuesday, April 26, 2016

JHipster Notes

JHipster.  I have always been a big fan of using framework / code generators to kick start apps where you just want to get something done but don't want to spend a lot of time laying in infrastructure and UI. In the past I have always used Grails for this purpose to pretty good effect. I have lots of utility apps that do a specific thing that, well, look a lot like a Grails app. This really allows me to quickly dive into the thing I wanted to get done. I was recently introduced to another project, JHipster, that uses code generation rather than a framework approach to kick start an application. Whereas Grails provides an application framework with a rich plugin architecture, JHipster takes the approach of generating your app from a BUNCH of best of breed technologies that would be needed in an enterprise web app.

What is it? At its core it pulls together Spring Boot on the back end and AngularJS on the front to create a modern looking application using tried and true enterprise architecture choices throughout. I won't include the laundry list of technologies within the generated app, but the highlights for me are the AngularJS/Bootstrap generated front end, Spring Boot using Spring Security and JPA with Spring Data JPA.

Javascript. I have been working on a largish sized AngularJS application at my full time job and have come to appreciate the size of Javascript/NodeJS ecosystem involved in standing up modern JS applications. JHipster takes full advantage of that ecosystem by generating a front end application that is in line with what a front end developer would expect. JHipster uses Yoeman, a fairly well known javascript code generator, to generate the application. Javascript dependencies are managed by Bower and you get a choice of Gulp/Grunt as your front end build tools. On my Macbook Pro I tend to have node versioning issues when using a lot of these tools, so I have installed NVM (Node Version Manager) to keep node under control.

Build. On the java side, you have a choice of build tools, Gradle or Maven, for the overall build.
 As this is a Spring Boot app, the java build tool is the main method for rendering the entire application, but it defers to the javascript build where it needs to.  The generator has you make this choice up front and I picked Gradle and Gulp for my build tooling.

Docker.  As of late I have also been playing with Docker to learn about quickly spinning up deploy environments.  JHipster generates a Docker directory in the src directory to provide the container set to deploy your app into.  In my case JHipster generated docker config for a java container and a postgresql container.  There was a bit of mystery for my around the postgresql container until I dug into it.  How did it know the db name, user name, password?  Where were all the commands necessary to create these things?  It turns out that the image that JHipster uses for Postgresql container, documents that you can just pass the user name as an environment variable on startup and it will use that to create the user, db, and password for you.  In my case the user name is simply my application name.

More to come.  I plan on using this blog to document the issues I come across as I take my JHipster generated app into a real working application that actually does more than CRUD. Topics I want to address in future blogs are Liquibase, SSL, JHipster Domain Language.

Thursday, April 21, 2016

TJUG Code Kata

Bob Damato and Shane Boucvalt of Valpak in St. Pete hosted the Tampa Java User Group (TJUG) Meetup tonight at Valpak's Manufacturing Center.  Tonight's meetup was run as a Code Kata, which is basically where a facilitator hands out a problem statement / requirement that can be solved/coded/tested within the space of a meeting in a safe environment where like minded developers can collaborate to solve the assigned issue.   The purpose behind the Kata is to give the developers a chance to practice their craft in that safe environment.  The problems are usually a generic puzzle style problems that require some thought goes into the solution and the unit testing scenarios.

Tonight's problem was called the Monty Hall problem.  From wikipedia:

Suppose you're on a game show, and you're given the choice of three doors: Behind one door is a car; behind the others, goats. You pick a door, say No. 1, and the host, who knows what's behind the doors, opens another door, say No. 3, which has a goat. He then says to you, "Do you want to pick door No. 2?" Is it to your advantage to switch your choice?

We were asked to run 2 - scenarios of 1000 runs each where the winning door and your guess are selected at random.  In  scenario 1, you stick with your first choice.  In scenario 2, you pick the remaining door.  The code is to determine which scenario has the advantage.  You could write in the language of your choice but given that this is the TJUG, java was kind of expected.  I choose Groovy because I like it and its close enough to Java that the others could read my code if I was explain it.  I wrote my tests in Spock and was happy that I could quickly spin up an app with a Gradle build and Spock tests within Intellij Idea.

It was a last minute decision on my part to attend as I was cutting it close to leave work at 5:30 pm in Tampa to get to St. Pete for the 6:30 meetup.  Because you so rarely get to do any coding in these type of user group meetings, I really wanted to attend this one.  It had a somewhat small turnout, but was interesting none the less.  It took me about an hour to get a working application that yielded the results.  My test were more about exercising my solution rather than checking the solution's validity.   Bob, Shane and other Valpak employee's who had previously done this Kata, shared their solutions and showed how to break testing down to 4 simple scenarios that validated the outcomes.  I was happy to have the opportunity to share my solution at the lectern with this small crowd.  I'm not always comfortable speaking in large group settings, so I was glad to have a chance to do this in this environment.

It was a really fun exercise and I look forward to sharing the Kata experience back at the office. Thanks to Bob and Shane, as well as Valpak for hosting this meetup. I am including both my code and tests for the Kata below.  More refactoring could be done but I wanted to post exactly what I ended up with in the allotted time:


KataMain.groovy

 package com.bpcs.kata  
 /**  
  * Main Kata for TJUG  
  *  
  * Created by wpfeiffe on 4/21/16.  
  */  
 class KataMain  
 {  
   public static void main(String[] args)  
   {  
     KataMain kataMain = new KataMain()  
     int winner = kataMain.runScenario()  
   }  
   int runScenario()  
   {  
     int winner = -1  
     Integer firstStrategyResult = this.getFirstStrategyResult()  
     Integer secondStrategyResult = this.getSecondStrategyResult()  
     println "The first strategy wins $firstStrategyResult times out of 1000"  
     println "The second strategy wins $secondStrategyResult times out of 1000"  
     if (secondStrategyResult > firstStrategyResult)  
     {  
       winner = 2  
     }  
     else if (firstStrategyResult > secondStrategyResult)  
     {  
       winner = 1  
     }  
     println "The winning strategy is $winner"  
     return winner  
   }  
   Integer getFirstStrategyResult()  
   {  
     Integer result = 0  
     List<Integer> doors = createItems()  
     List<Integer> guesses = createItems()  
     doors.eachWithIndex{ int door, int i ->  
       // if they picked correctly  
       if (door == guesses[i])  
       {  
         result++  
       }  
     }  
     return result  
   }  
   Integer getSecondStrategyResult()  
   {  
     Integer result = 0  
     List<Integer> doors = createItems()  
     List<Integer> guesses = createItems()  
     doors.eachWithIndex{ int door, int i ->  
       // if they did NOT pick correctly  
       if (door != guesses[i])  
       {  
         result++  
 //        Integer nextPick = pickRandomDoor(2)  
 //        if (guesses[i] == 1)  
 //        {  
 //          nextPick++  
 //        }  
 //        else if (guesses[i] == 2)  
 //        {  
 //          if (nextPick == 2)  
 //          {  
 //            nextPick++  
 //          }  
 //        }  
 //        else  
 //        {}  
 //        if (door == nextPick)  
 //        {  
 //          result++  
 //        }  
       }  
       // else they change and result is 0  
     }  
     return result  
   }  
   List<Integer> createItems()  
   {  
     List<Integer> items = []  
     (1..1000).each {  
       items << pickRandomDoor(3)  
     }  
     return items  
   }  
   Integer pickRandomDoor(int max)  
   {  
     Random rand = new Random()  
     rand.nextInt(max) + 1  
   }  
 }  

KataMainSpec.groovy

 package com.bpcs.kata  
 import spock.lang.*  
 /**  
  * Spock tests for TJUG Kata  
  *  
  * Created by wpfeiffe on 4/21/16.  
  */  
 class KataMainSpec extends Specification  
 {  
   def "Test Create Items"() {  
     setup:  
       KataMain kataMain = new KataMain()  
     when:  
       List<Integer> items = kataMain.createItems()  
     then:  
       items != null && items.size() == 1000  
   }  
   def "Test Random Door"()  
   {  
     setup:  
     KataMain kataMain = new KataMain()  
     when:  
     Integer door = kataMain.pickRandomDoor(3)  
     then:  
     door > 0 && door < 4  
   }  
   def "Test First Strategy"(){  
     setup:  
     KataMain kataMain = new KataMain()  
     when:  
     Integer successCount = kataMain.getFirstStrategyResult()  
     println "First result = $successCount"  
     then:  
     successCount >= 0 && successCount <= 1000  
   }  
   def "Test Second Strategy"(){  
     setup:  
     KataMain kataMain = new KataMain()  
     when:  
     Integer successCount = kataMain.getSecondStrategyResult()  
     println "Second result = $successCount"  
     then:  
     successCount >= 0 && successCount <= 1000  
   }  
   def "Test All"() {  
     setup:  
     KataMain kataMain = new KataMain()  
     when:  
     Integer winner = kataMain.runScenario()  
     then:  
     winner >= 1 && winner <= 2  
   }  
 }  

build.gradle

 group 'com.bpcs.kata'  
 version '1.0-SNAPSHOT'  
 apply plugin: 'groovy'  
 apply plugin: 'java'  
 sourceCompatibility = 1.8  
 repositories {  
   mavenCentral()  
 }  
 dependencies {  
   compile 'org.codehaus.groovy:groovy-all:2.4.4'  
   testCompile group: 'junit', name: 'junit', version: '4.12'  
   testCompile 'org.spockframework:spock-core:1.0-groovy-2.4'  
 }