building smart dashboard with gradle

Main menu:

Topics

Recent Posts

Feeds

RSS Feed RSS - Posts

January 2017
M T W T F S S
« Dec    
 1
2345678
9101112131415
16171819202122
23242526272829
3031  

Past Posts

Java/Java EE

JDBC

Other

building smart dashboard with gradle

January 14th, 2017 by Jeanne Boyarsky

FRC (FIRST Robotics Challenge) uses Ant to build the robot code. I think this is a wise choice since some teams are “internet challenged.” This hasn’t changed. What has changed since last year is that SmartDashboard uses Gradle to build. Our team is thinking about customizing Smart Dashboard this year which means we need to be able to build it.

Yesterday in the FRC lab, one of the StuyPulse team members asked me about Gradle. (I gave a really good overview of Ant last year so they remembered I knew build tools.) I explained the concepts of Maven/Gradle especially the local repository and dependencies. And I verbally explained how to run it. We didn’t get to do so together as there were other priorities for the day. And a lot of people weren’t at the meeting due to a competing school event. So I’m writing everything down in this post.

Building Smart Dashboard

The discussion was centered around building SmartDashboard. If you aren’t involved with a FIRST Robotics Competition team, this is a Java based UI used when running the robot. Conveniently that project comes with Gradle right in the project. So all you have to is:

  1. cd to directory you cloned SmartDashboard in
  2. chmod 700 gradlew
  3. ./gradlew build

Make sure you have internet before running this the first time. If you want to build directly from Eclipse, see my Eclipse Gradle post

Where is the output when building SmartDashboard

Running gradle creates a build directory. If you are using Eclipse, remember to hit refresh before looking for it. This build directory  contains a number of things:

  • distributions – a zipped up and tarred up version of SmartDashboard which includes the jar file, all need dependencies and the script to kick it off. This is what you need
  • classes – the compiled .class files
  • libs – a jar file with the compiled code in this project
  • reports – how well did you follow the coding standards established for this project
  • scripts – to launch SmartDashboard
  • temp – would you really expect to find something important in a directory named temp?

What does the Gradle build file do?
Gradle is a build tool. The build.gradle file in SmartDashboard contains Groovy code that declares what the build should do. Both Gradle and Maven follow “convention over configuration” which means that a lot is implied! I went over most (but not all) of this out loud in the classroom.

A plugin is like a helper tool that Gradle is going to use in order to build. For example, ‘java’ is going to compile among other things.  Most of these plugins are in common use. I hadn’t heard of the shadow before. A quick look tells me that it builds an uber jar (which is a distribution file that contains all the dependencies). That’s really useful. In fact, I have used the shade plugin which does the same thing in Maven. The WPILibVersioningPlugin is obviously specialized code for FIRST.

plugins {
    id 'java'
    id 'application'
    id 'com.github.johnrengelman.shadow' version '1.2.4'
    id 'maven-publish'
    id 'idea'
    id 'edu.wpi.first.wpilib.versioning.WPILibVersioningPlugin' version '1.6'
    id 'checkstyle'
}

Gradle needs to download files in order to run. This includes the plugins that we just saw along with dependencies – jars that the program needs. These files are hosted in a repository for binary files. A really common one is Maven Central. This is used by both Maven and Gradle builds to obtain binaries.

repositories {
    mavenCentral()
}

Those dependencies I just mentioned? Here they are. In this case, the dependencies are WPI code and common open source tools like JUnit (a testing library). Notice how all of these except the WPI one use the same format – three strings separated by colons? There’s a reason for this. When accessing Maven Central, you specify a GAV. This stands for group id/artifact id/version. The colons separate them. For example, jfree is a group id, jfreechart is an artifact id and 1.0.13 is a version.

Note that none of these four exhibits a “normal” GAV. You are supposed to use a fully qualified name for the group id. Just like we do for Java package names. An artifact id is lower case “words” separated by dashes if there is more than one word. Finally, you have an optional version number.  There can also be some optional information like a classifier that tells you what file extension you need. The WPI example does have a good group id. And the others have good artifact ids and versions. For more on the WPILib group id see this post.

dependencies {
    compile 'edu.wpi.first.wpilib.networktables.java:NetworkTables:+:desktop'
    compile 'junit:junit:4.12'
    compile 'jfree:jcommon:1.0.16'
    compile 'jfree:jfreechart:1.0.13'
}

Next the script specifies that we should create a jar file and an uber jar file named SmartDashboard.

jar {
    baseName = 'SmartDashboard'
}
shadowJar {
    baseName = 'SmartDashboard'
}

Now you see that this really is a Groovy script; it even has an if statement.

// Ensure that the WPILibVersioningPlugin is setup by setting the release type, if releaseType wasn't
// already specified on the command line
if (!hasProperty('releaseType')) {
    WPILibVersion {
        releaseType = 'dev'
    }
}

If the artifact is being published, details are here. WPI is publishing to this FIRST WPI Maven repo. They use the WPI Version Plugin and publish to the local Maven repo – which is the FIRST WPI Maven repo on their build server. (clarified in comment 65)

publishing {
    publications {
        maven(MavenPublication) {
            artifact(shadowJar) {
                classifier null
            }
            groupId 'edu.wpi.first.wpilib'
            artifactId 'SmartDashboard'
            version WPILibVersion.version
        }
    }
}

Getting close to the end. Now the build configuration says to use the coding conventions in the checkstyle.xml file. This is good. It means that people will have to follow coding conventions if they contribute back to SmartDashboard.

checkstyle {
    configFile = new File(rootDir, "checkstyle.xml")
    toolVersion = '6.19'
    if (project.hasProperty("ignoreCheckstyle")) {
        ignoreFailures = true
    }
}

In Java, you can automatically configure a Jar to run a certain class’ main method when you run the jar. This is specified in the manifest. Gradle can generate this manifest for you.

mainClassName = "edu.wpi.first.smartdashboard.SmartDashboard"

SmartDashboard comes with a fakeRobot test project. This is a submodule from Gradle’s point of view so it needs a build config too. Luckily you already know what plugins, dependencies and a main class are so this should be clear.

project(':fakeRobot') {
  apply plugin: 'java'
  apply plugin: 'application'

  dependencies {
      compile 'edu.wpi.first.wpilib.networktables.java:NetworkTables:+:desktop'
  }

  mainClassName = "edu.wpi.livewindowfakerobot.LiveWindowFakeRobot"
}

The end! The very last thing is to declare which version of Gradle this entire script should be run with.

task wrapper(type: Wrapper) {
    gradleVersion = '3.3'
}

Output from building in gradle

I’m including the output from a “good” run in case you have problems and want to compare. This is for the first time you run it. After that the download steps won’t be in the output and it will run much faster.

$ ./gradlew build
Downloading https://services.gradle.org/distributions/gradle-3.3-bin.zip
…………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………..
Unzipping /Users/jeanne/.gradle/wrapper/dists/gradle-3.3-bin/64bhckfm0iuu9gap9hg3r7ev2/gradle-3.3-bin.zip to /Users/jeanne/.gradle/wrapper/dists/gradle-3.3-bin/64bhckfm0iuu9gap9hg3r7ev2
Set executable permissions for: /Users/jeanne/.gradle/wrapper/dists/gradle-3.3-bin/64bhckfm0iuu9gap9hg3r7ev2/gradle-3.3/bin/gradle
Starting a Gradle Daemon (subsequent builds will be faster)
Download https://plugins.gradle.org/m2/com/github/jengelman/gradle/plugins/shadow/1.2.4/shadow-1.2.4.pom
Download https://plugins.gradle.org/m2/gradle/plugin/edu/wpi/first/wpilib/versioning/wpilib-version-plugin/1.6/wpilib-version-plugin-1.6.pom
Download https://plugins.gradle.org/m2/org/ow2/asm/asm-commons/5.0.3/asm-commons-5.0.3.pom
Download https://plugins.gradle.org/m2/org/apache/ant/ant/1.9.4/ant-1.9.4.pom
Download https://plugins.gradle.org/m2/org/apache/ant/ant-parent/1.9.4/ant-parent-1.9.4.pom
Download https://plugins.gradle.org/m2/org/codehaus/groovy/groovy-backports-compat23/2.4.4/groovy-backports-compat23-2.4.4.pom
Download https://plugins.gradle.org/m2/org/ajoberstar/grgit/1.7.0/grgit-1.7.0.pom
Download https://plugins.gradle.org/m2/org/apache/ant/ant-launcher/1.9.4/ant-launcher-1.9.4.pom
Download https://plugins.gradle.org/m2/org/eclipse/jgit/org.eclipse.jgit/4.3.1.201605051710-r/org.eclipse.jgit-4.3.1.201605051710-r.pom
Download https://plugins.gradle.org/m2/org/eclipse/jgit/org.eclipse.jgit-parent/4.3.1.201605051710-r/org.eclipse.jgit-parent-4.3.1.201605051710-r.pom
Download https://plugins.gradle.org/m2/org/eclipse/jgit/org.eclipse.jgit.ui/4.3.1.201605051710-r/org.eclipse.jgit.ui-4.3.1.201605051710-r.pom
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.jsch/0.0.9/jsch.agentproxy.jsch-0.0.9.pom
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy/0.0.9/jsch.agentproxy-0.0.9.pom
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.pageant/0.0.9/jsch.agentproxy.pageant-0.0.9.pom
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.sshagent/0.0.9/jsch.agentproxy.sshagent-0.0.9.pom
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.usocket-jna/0.0.9/jsch.agentproxy.usocket-jna-0.0.9.pom
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.usocket-nc/0.0.9/jsch.agentproxy.usocket-nc-0.0.9.pom
Download https://plugins.gradle.org/m2/org/slf4j/slf4j-api/1.7.21/slf4j-api-1.7.21.pom
Download https://plugins.gradle.org/m2/org/slf4j/slf4j-parent/1.7.21/slf4j-parent-1.7.21.pom
Download https://plugins.gradle.org/m2/com/jcraft/jsch/0.1.53/jsch-0.1.53.pom
Download https://plugins.gradle.org/m2/com/googlecode/javaewah/JavaEWAH/0.7.9/JavaEWAH-0.7.9.pom
Download https://plugins.gradle.org/m2/org/sonatype/oss/oss-parent/5/oss-parent-5.pom
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.core/0.0.9/jsch.agentproxy.core-0.0.9.pom
Download https://plugins.gradle.org/m2/com/github/jengelman/gradle/plugins/shadow/1.2.4/shadow-1.2.4.jar
Download https://plugins.gradle.org/m2/gradle/plugin/edu/wpi/first/wpilib/versioning/wpilib-version-plugin/1.6/wpilib-version-plugin-1.6.jar
Download https://plugins.gradle.org/m2/org/ow2/asm/asm-commons/5.0.3/asm-commons-5.0.3.jar
Download https://plugins.gradle.org/m2/org/apache/ant/ant/1.9.4/ant-1.9.4.jar
Download https://plugins.gradle.org/m2/org/codehaus/groovy/groovy-backports-compat23/2.4.4/groovy-backports-compat23-2.4.4.jar
Download https://plugins.gradle.org/m2/org/ajoberstar/grgit/1.7.0/grgit-1.7.0.jar
Download https://plugins.gradle.org/m2/org/apache/ant/ant-launcher/1.9.4/ant-launcher-1.9.4.jar
Download https://plugins.gradle.org/m2/org/eclipse/jgit/org.eclipse.jgit/4.3.1.201605051710-r/org.eclipse.jgit-4.3.1.201605051710-r.jar
Download https://plugins.gradle.org/m2/org/eclipse/jgit/org.eclipse.jgit.ui/4.3.1.201605051710-r/org.eclipse.jgit.ui-4.3.1.201605051710-r.jar
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.jsch/0.0.9/jsch.agentproxy.jsch-0.0.9.jar
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.pageant/0.0.9/jsch.agentproxy.pageant-0.0.9.jar
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.sshagent/0.0.9/jsch.agentproxy.sshagent-0.0.9.jar
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.usocket-jna/0.0.9/jsch.agentproxy.usocket-jna-0.0.9.jar
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.usocket-nc/0.0.9/jsch.agentproxy.usocket-nc-0.0.9.jar
Download https://plugins.gradle.org/m2/org/slf4j/slf4j-api/1.7.21/slf4j-api-1.7.21.jar
Download https://plugins.gradle.org/m2/com/jcraft/jsch/0.1.53/jsch-0.1.53.jar
Download https://plugins.gradle.org/m2/com/googlecode/javaewah/JavaEWAH/0.7.9/JavaEWAH-0.7.9.jar
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.core/0.0.9/jsch.agentproxy.core-0.0.9.jar
No .git was found in /Users/jeanne/Documents/workspace/SmartDashboard, or any parent directories of that directory.
No version number generated.
:compileJava
Download http://first.wpi.edu/FRC/roborio/maven/development/edu/wpi/first/wpilib/networktables/java/NetworkTables/3.1.5-20170105171843-1-g3e2631f/NetworkTables-3.1.5-20170105171843-1-g3e2631f.pom
Download https://repo1.maven.org/maven2/jfree/jcommon/1.0.16/jcommon-1.0.16.pom
Download https://repo1.maven.org/maven2/jfree/jfreechart/1.0.13/jfreechart-1.0.13.pom
Download http://first.wpi.edu/FRC/roborio/maven/development/edu/wpi/first/wpilib/networktables/java/NetworkTables/3.1.5-20170105171843-1-g3e2631f/NetworkTables-3.1.5-20170105171843-1-g3e2631f-desktop.jar
Download https://repo1.maven.org/maven2/jfree/jcommon/1.0.16/jcommon-1.0.16.jar
Download https://repo1.maven.org/maven2/jfree/jfreechart/1.0.13/jfreechart-1.0.13.jar
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
:processResources UP-TO-DATE
:classes
:jar
:startScripts
:distTar
:distZip
:assemble
:checkstyleMain
Download https://repo1.maven.org/maven2/com/puppycrawl/tools/checkstyle/6.19/checkstyle-6.19.pom
Download https://repo1.maven.org/maven2/org/antlr/antlr4-runtime/4.5.3/antlr4-runtime-4.5.3.pom
Download https://repo1.maven.org/maven2/org/antlr/antlr4-master/4.5.3/antlr4-master-4.5.3.pom
Download https://repo1.maven.org/maven2/commons-cli/commons-cli/1.3.1/commons-cli-1.3.1.pom
Download https://repo1.maven.org/maven2/com/puppycrawl/tools/checkstyle/6.19/checkstyle-6.19.jar
Download https://repo1.maven.org/maven2/org/antlr/antlr4-runtime/4.5.3/antlr4-runtime-4.5.3.jar
Download https://repo1.maven.org/maven2/commons-cli/commons-cli/1.3.1/commons-cli-1.3.1.jar
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:checkstyleTest UP-TO-DATE
:test UP-TO-DATE
:check
:build
:fakeRobot:compileJava
:fakeRobot:processResources UP-TO-DATE
:fakeRobot:classes
:fakeRobot:jar
:fakeRobot:startScripts
:fakeRobot:distTar
:fakeRobot:distZip
:fakeRobot:assemble
:fakeRobot:compileTestJava UP-TO-DATE
:fakeRobot:processTestResources UP-TO-DATE
:fakeRobot:testClasses UP-TO-DATE
:fakeRobot:test UP-TO-DATE
:fakeRobot:check UP-TO-DATE
:fakeRobot:build

BUILD SUCCESSFUL

Total time: 1 mins 9.099 secs

gradle in eclipse – egradle vs buildship

January 14th, 2017 by Jeanne Boyarsky

TLDR: use BuildShip rather than EGradle.

While everyone on our team uses command line git (rather than egit), most actual coding in Java happens within Eclipse. We ran Ant in Eclipse for deploying robot code and Ant at the command line for other things. I’m not sure if we will use Eclipse to run Gradle, but writing up for the team just in case!

For more on what the Gradle files mean see the main Gradle SmartDashboard post

EGradle

The first thing I did was try out the EGradle plugin. It worked, but wasn’t as smooth as BuildShip. (See below for using BuildShip).

Install EGradle

  1. Help
  2. Eclipse Marketplace
  3. EGradle
  4. Accept license and install
  5. Restart Eclipse

Modify the project you cloned from github

  1. Clone SmartDashboard if you haven’t already
  2. Edit the build.gradle file to add the eclipse profile.  You just have to add the one line and save the file:
    project(':fakeRobot') {
      apply plugin: 'java'
      apply plugin: 'application'
      apply plugin: 'eclipse'

Import the project you cloned from github

  1. File
  2. Import
  3. EGradle > Import gradle root project with all subprojects
  4. Set Gradle root project to the repository you cloned from github

Build

  1. Right click the build.gradle file
  2. Run as > EGradle

EGradle limitations

  1. You had to edit the build.gradle for Eclipse to recognize it.
  2. EGradle doesn’t provide a way to see the build directory so you have to go to the file system. (and yes I tried changing the filters; it just didn’t work)

Trying that again with BuildShip

BuildShip is the official Eclipse.org plugin for Gradle. Wish I knew that before I started!

Install BuildShip

  1. Help
  2. Eclipse Marketplace
  3. BuildShip Gradle Integration
  4. Accept license and install
  5. Restart Eclipse

Import the project you cloned from github

  1. File
  2. Import
  3. Gradle >Existing Gradle project
  4. Set project root directory to the repository you cloned from github (Note that you don’t need to edit the build.gradle file like you had to with EGradle). It also uses the proper project name.

Build

There are multiple ways to do this. I’m showing just one way that maximizes understanding of what is going on.

  1. The Gradle Tasks view is open automatically for this project. (If not, click the project)
  2. Click SmartDashboard to expand
  3. Click build to expand
  4. Right click build (with a green icon to the left) and choose “Run Gradle Tasks”
  5. This automatically opens the Gradle Executions view which shows you what Gradle did in a nice tree. You can click on the Console view to see the actual command line output.
  6.  F5 to refresh – now you see the build folder.

 

The 8 Nights of Java – Night 8

December 31st, 2016 by Jeanne Boyarsky

It’s been a fun 8 Nights of Java, but alas, tonight is the final post. Java 8 added one of the most radical, most drastic changes to date, even bigger than Java 5 or Java 7: lambdas and streams! The writers of Java updated nearly every Java API to include lambda expression and stream-based methods. More than the API changes, though, they present a new paradigm for thinking about programming. The closest thing to a lambda expression prior to Java 8 was an anonymous inner class, and it a lot of ways they are similar, but the syntax and usability of lambda expressions is unmatched.

We hope everyone had a wonderful holiday season and we hope that you have a Happy New Year! Don’t forget, we have a brand new OCA/OCP 8 book coming out in March 2017. Order yours now on Amazon.com!

Jump to: [Night 1 | Night 2 | Night 3 | Night 4 | Night 5 | Night 6 | Night 7 | Night 8]

Java 8 Notable Features

Oracle released Java 8 on March 18, 2014. If you’ve read the previous nights in this series, you might be wondering what the codename of Java 8 was. Oracle decided not to use one. Luckily, our friends at the Javaranch had some ideas. We like “Cuddles” ourselves.

Key new functionality included:

  • Functional interfaces
  • Lambda expressions
  • Streams
  • New date/time library
  • Project Nashorn

From Jeanne:

Streams and lambdas are one of my favorite additions to the language of all time. They make it easy to write expressive code. I haven’t needed the benefits of multi-core parallelization much yet, but it is nice to know it is there. Even without that, I find my stream based code to be shorter and easy to write/read. It took me a little while to get fluent but I went through that with Groovy before Java so I was ready when it came to Java. I was the first person on my team to write a Java 8 program for work. I commented almost every line so it could be used as a teaching example. That was fun!

The date/time library is also cool. I like that it is expressive and has so much more functionality than the Calendar API. Third time for a date API really was the charm. I just wish they retrofitted it to work directly with more libraries like JDBC. Then there’s Nashorn. A JavaScript console was a good idea, but I don’t think this one is it.

From Scott:

Two things I love about lambda expressions and streams in Java 8. First, they found a way to build functional programming into Java, by using functional interfaces. While the signature for some of the built-in functional interfaces can be… hard to read… using or creating lambda expressions rarely requires understanding the signature. That’s what is so cool about what they did. They added this conversion of lambda expressions to functional interfaces to anonymous inner classes, but from a developers perspective, all we have to know how to do is write a simple one-line lambda expression! Very cool they way they added this on without breaking the language.

The second thing I love is they included parallel streams in the very first version! It’s so awesome to be able to have built-in easy support for concurrency without having to create/manage/shutdown an executor service. One feature request for Java 9? I *really* would prefer a way to set the number of threads in a parallel stream, such as stream.parallel(10) for 10 threads. Currently, it’s controlled by the JVM based on the number of threads on the computer and unable to be changed by a developer. Here’s hoping they add it to a future version of Java!

There’s still so much more to love about Java 8! As I was saying on Night 7, Java 7 improved the Concurrency API while introducing NIO.2, but both became even more powerful in Java 8. Creating Runnable and Callable instances using anonymous inner classes was already common prior to Java 8, but it was at times verbose. You had to create a class definition, override a method, set up a generic return type for Callable, etc. While not difficult to do, it did take up multiple lines of bloated code, copied over and over again for each task. Lambda expressions fit perfectly in the Concurrency API, better than any other API (with the possible exception of Collections), in that it allowed developers to submit tasks to a thread executor in a single, simple line of code using a lambda expression. In other words, they made Concurrency, one of the arguably most difficult spaces for developers to work in, much easier to understand and implement.