Category Archives: Gradle

PHPHOST BLOG

Web Hosting Related Articles You May Need

Compiling and Running Java Without an IDE

A recent Java subreddit thread called “Compiling Java Packages without IDE” posed the question, “is [there] a command that compiles a group of java files that are inside a package into a separate folder (let’s just call it bin), and how would I go about running the new class files?” The post’s author, kylolink, explains that “When I started out using Java I relied on Eclipse to do all the compiling for me and just worried about writing code.” I have seen this issue many times and, in fact, it’s what prompted my (now 4 years old) blog post GPS Systems and IDEs: Helpful or Harmful? I love the powerful modern Java IDEs and they make my life easier on a daily basis, but there are advantages to knowing how to build and run simple Java examples without them. This post focuses on how to do just that.

In my blog post Learning Java via Simple Tests, I wrote about how I sometimes like to use a simple text editor and command-line tools to write, build, and run simple applications. I have a pretty good idea now how my much “overhead” my favorite Java IDEs require and make an early decision whether the benefits achieved from using the IDE are sufficient to warrant the “overhead.” In most real applications, there’s no question the IDE “overhead” is well worth it. However, for the simplest of example applications, this is not always the case. The rest of this post shows how to build and run Java code without an IDE for these situations.

The Java Code to be Built and Executed

To make this post’s discussion more concrete, I will use some very simple Java classes that are related to each other via composition or inheritance and are in the same named package (not in the unnamed package) called dustin.examples. Two of the classes do not have main functions and the third class, Main.java does have a main function to allow demonstration of running the class without an IDE. The code listings for the three classes are shown next.

Parent.java


package dustin.examples;

public class Parent
{
@Override
public String toString()
{
return "I'm the Parent.";
}
}

Child.java


package dustin.examples;

public class Child extends Parent
{
@Override
public String toString()
{
return "I'm the Child.";
}
}

Main.java


package dustin.examples;

import static java.lang.System.out;

public class Main
{
private final Parent parent = new Parent();
private final Child child = new Child();

public static void main(final String[] arguments)
{
final Main instance = new Main();
out.println(instance.parent);
out.println(instance.child);
}
}

The next screen snapshot shows the directory structure with these class .java source files in place. The screen snapshot shows that the source files are in a directory hierarchy representing the package name (dustin/examples because of package dustin.examples) and that this package-reflecting directory hierarchy is under a subdirectory called src. I have also created classes subdirectory (which is currently empty) to place the compiled .class files because javac will not create that directory when it doesn’t exist.

Building with javac and Running with java

No matter which approach one uses to build Java code (Ant, Maven, Gradle, or IDE) normally, I believe it is prudent to at least understand how to build Java code with javac. The Oracle/Sun-provided javac command-line tool‘s standard options can be seen by running javac -help and additional extension options can be viewed by running javac -help -X. More details on how to apply these options can be found in the tools documentation for javac for Windows or Unix/Linux.

As the javac documentation states, the -sourcepath option can be use to express the directory in which the source files exist. In my directory structure shown in the screen snapshot above, this would mean that, assuming I’m running the javac command from the C:\java\examples\javacAndJava\ directory, I’d need to have something like this in my command: javac -sourcepath src src\dustin\examples\*.java. The next screen snapshot shows the results of this.

Because we did not specify a destination directory for the .class files, they were placed by default in the same directory as the source .java files from which they were compiled. We can use the -d option to rectify this situation. Our command could be run now, for example, as javac -sourcepath src -d classes src\dustin\examples\*.java. As stated earlier, the specified destination directory (classes) must already exist. When it does, the command will place the .class files in the designated directory as shown in the next screen snapshot.

With the Java source files compiled into the appropriate .class files in the specified directory, we can now run the application using the Java application launcher command line tool java. This is simply done by following the instructions shown by java -help or by the java tools page and specifying the location of the .class files with the -classpath (or -cp) option. Using both approaches to specify that the classes directory is where to look for the .class files is demonstrated in the next screen snapshot. The last argument is the fully qualified (entire Java package) name of the class who has a main function to be executed. The commands demonstrated in the next screen snapshot is java -cp classes dustin.examples.Main and java -classpath classes dustin.examples.Main.

Building and Running with Ant

For the simplest Java applications, it is pretty straightforward to use javac and java to build and execute the application respectively as just demonstrated. As the applications get a bit more involved (such as code existing in more than one package/directory or more complex classpath dependencies on third-party libraries and frameworks), this approach can become unwieldy. Apache Ant is the oldest of the “big three” of Java build tools and has been used in thousands of applications and deployments. As I discussed in a previous blog post, a very basic Ant build file is easy to create, especially if one starts with a template like I outlined in that post.

The next code listing is for an Ant build.xml file that can be use to compile the .java files into .class files and then run the dustin.examples.Main class just like was done above with javac and java.

build.xml


<?xml version="1.0" encoding="UTF-8"?>
<project name="BuildingSansIDE" default="run" basedir=".">
<description>Building Simple Java Applications Without An IDE</description>

<target name="compile"
description="Compile the Java code.">
<javac srcdir="src"
destdir="classes"
debug="true"
includeantruntime="false" />
</target>

<target name="run" depends="compile"
description="Run the Java application.">
<java classname="dustin.examples.Main" fork="true">
<classpath>
<pathelement path="classes"/>
</classpath>
</java>
</target>
</project>

I have not used Ant properties and not included common targets I typically include (such as “clean” and “javadoc”) to keep this example as simple as possible and to keep it close to the previous example using javac and java. Note also that I’ve included “debug” set to “true” for the javac Ant task because it’s not true in Ant’s default but is true with javac’s default. Not surprisingly, Ant’s javac task and java task closely resemble the command tools javac and java.

Because I used the default name Ant expects for a build file when it’s not explicitly specified (build.xml) and because I provided the “run” target as the “default” for that build file and because I included “compile” as a dependency to run the “run” target and because Ant was on my environment’s path, all I need to do on the command line to get Ant to compile and run the example is type “ant” in the directory with the build.xml file. This is demonstrated in the next screen snapshot.

Although I demonstrated compiling AND running the simple Java application with Ant, I typically only compile with Ant and run with java (or a script that invokes java if the classpath is heinous).

Building and Running with Maven

Although Ant was the first mainstream Java build tool, Apache Maven eventually gained its own prominence thanks in large part to its adoption of configuration by convention and support for common repositories of libraries. Maven is easiest to use when the code and generated objects conform to its standard directory layout. Unfortunately, my example doesn’t follow this directory structure, but Maven does allow us to override the expected default directory structure. The next code listing is for a Maven POM file that overrides the source and target directories and provides other minimally required elements for a Maven build using Maven 3.2.1.

pom.xml


<project>
<modelVersion>4.0.0</modelVersion>
<groupId>dustin.examples</groupId>
<artifactId>CompilingAndRunningWithoutIDE</artifactId>
<version>1</version>

<build>
<defaultGoal>compile</defaultGoal>
<sourceDirectory>src</sourceDirectory>
<outputDirectory>classes</outputDirectory>
<finalName>${project.artifactId}-${project.version}</finalName>
</build>
</project&gt

Because the above pom.xml file specifies a “defaultGoal” of “compile” and because pom.xml is the default custom POM file that the Maven executable (mvn) looks for and because the Maven installation’s bin directory is on my path, I only needed to run “mvn” to compile the .class files as indicated in the next screen snapshot.

I can also run the compiled application with Maven using the command mvn exec:java -Dexec.mainClass=dustin.examples.Main, which is demonstrated in the next screen snapshot.

As is the case with Ant, I would typically not use Maven to run my simple Java application, but would instead use java on the compiled code (or use a script that invokes java directly for long classpaths).

Building and Running with Gradle

Gradle is the youngest, trendiest, and hippest of the three major Java build tools. I am sometimes skeptical of the substance of something that is trendy, but I have found many things to like about Gradle (written in Groovy instead of XML, built-in Ant support, built-in Ivy support, configuration by convention that is easily overridden, Maven repository support, etc.). The next example shows a Gradle build file that can be used to compile and run the simple application that is the primary example code for this post. It is adapted from the example I presented in the blog post Simple Gradle Java Plugin Customization.

build.gradle


apply plugin: 'java'
apply plugin: 'application'

// Redefine where Gradle should expect Java source files (*.java)
sourceSets {
main {
java {
srcDirs 'src'
}
}
}

// Redefine where .class files are written
sourceSets.main.output.classesDir = file("classes")

// Specify main class to be executed
mainClassName = "dustin.examples.Main"

defaultTasks 'compileJava', 'run'

The first two lines of the build.gradle file specify application of the Java plugin and the Application plugin, bringing a bunch of functionality automatically to this build. The definition of “sourceSets” and “sourceSets.main.output.classesDir” allows overriding of Gradle’s Java plugin’s default directories for Java source code and compiled binary classes respectively. The “mainClassName” allows explicit specification of which class should be run as part of the Application plugin. The “defaultTasks” line specifies the tasks to be run by simply typing “gradle” at the command line: ‘compileJava’ is a standard task provided by the Java plugin and ‘run’ is a standard task provided by the Application plugin. Because I named the build file build.gradle and because I specified the default tasks of ‘compileJava’ and ‘run’ and because I have the Gradle installation bin directory on my path, all I needed to do to build and run the examples was to type “gradle” and this is demonstrated in the next screen snapshot.

Even the biggest skeptic has to admit that Gradle build is pretty slick for this simple example. It combines brevity from relying on certain conventions and assumptions with a very easy mechanism for overriding select defaults as needed. The fact that it’s in Groovy rather than XML is also very appealing!

As is the case with Ant and Maven, I tend to only build with these tools and typically run the compiled .class files directly with java or a script that invokes java. By the way, I typically also archive these .class into a JAR for running, but that’s outside the scope of this post.

Conclusion

An IDE is often not necessary for building simple applications and examples and can even be more overhead than it’s worth for the simplest examples. In such a case, it’s fairly easy to apply javac and java directly to build and run the examples. As the examples become more involved, a build tool such as Ant, Maven, or Gradle becomes more appealing. The fact that many IDEs support these build tools means that a developer could transition to the IDE using the build tool created earlier in the process if it was determined that IDE support was needed as the simple application grew into a full-fledged project.

Original posting available at http://marxsoftware.blogspot.com/ (Inspired by Actual Events)

Continue reading

Posted in Ant, Gradle, Java (General), Maven, Syndicated | Comments Off on Compiling and Running Java Without an IDE

Specifying Gradle Build Properties

Properties are a valuable tool for easily customizing Gradle builds and the Gradle environment. I demonstrate some of these approaches for specifying properties used in a Gradle build in this post.

Gradle supports both project properties and system properties. The main difference between the two that is of interest in this post is how each is accessed. Project properties are more conducive to direct access by name while system properties are accessed via normal Java/Groovy system properties access methods.

Passing Project Properties from Command-Line with -P

One of the easiest approaches for passing properties to a Gradle build is to specify project properties with -P from the command line. Properties passed into the build with -P are readily accessible in the build as project properties and, if their naming structure allows, can be accessed directly like variables.

Passing System Properties from Command-Line with -D

As is the case with other Java applications, one can pass system properties to Gradle builds with -D. Although these system properties provided to the Gradle build via the -D option are always available to the Gradle build via the normal Java mechanism for obtaining system properties, Gradle makes it possible to specify Project Properties as system properties. This is done by placing the prefix org.gradle.project. before the name of the property desired in the build. For example, if one wanted to specify a system property named name.first with -D that would be available to the Gradle build as if it was provided with -P, the person could provide it to the Gradle build on the command line as org.gradle.project.name.first and the Gradle build would see it as a project property named name.first.

Passing System Properties via Environmental Variable

Any Java or Groovy application (including a Gradle build) can access environmental variables via System.getenv(String). However, Gradle allows environment variables to be accessed within the build like other project properties if the environmental variable is prefixed with ORG_GRADLE_PROJECT_. For example, if one wanted a project property in the Gradle build to be called name.last and wanted to supply it to the build via environment variable, that person could declare the environment variable ORG_GRADLE_PROJECT_name.last and its value would be available to the Gradle build as a project property with name name.last.

gradle.properties

Properties can also be provided to a Gradle build via a properties file named gradle.properties. Any properties specified with systemProp. at the beginning of their property name are seen as system properties in the Gradle build and other properties (without their names beginning with “systemProp.”) are seen as Gradle project properties. For example, if my gradle.properties file had a property name.last=Marx and a property systemPropr.name.first=Dustin, the name.last property would be seen and accessed in the Gradle build like any project property while the name.first property would be seen and accessed in the Gradle build like any system property.

Demonstration / Example

Each of these types of properties-specifying mechanisms can be demonstrated with a simple example. The Gradle build shown next attempts to print out various properties that are specified in different ways.

build-properties.gradle


task displayProperties displaySystemProperties()
displayGradleProjectProperties()
}

def displaySystemProperties()
{
println "\n=== System Properties ==="
println "Favorite Movie (1994): ${System.properties['movie.favorite.1994']}"
println "Favorite Movie (1996): ${System.properties['movie.favorite.1996']}"
println "Favorite Movie (1997): ${System.properties['movie.favorite.1997']}"
println "Favorite Movie (1981): ${System.properties['movie.favorite.1981']}"
println "Favorite Movie (2012): ${System.properties['movie.favorite.2012']}"
println "Favorite Movie (2013): ${System.properties['movie.favorite.2013']}"
}

def displayGradleProjectProperties()
{
println "\n=== Gradle Project Properties ==="
println "Favorite Movie (1994): ${getProjectProperty('movie.favorite.1994')}"
println "Favorite Movie (1996): ${getProjectProperty('movie.favorite.1996')}"
println "Favorite Movie (1997): ${getProjectProperty('movie.favorite.1997')}"
println "Favorite Movie (1981): ${getProjectProperty('movie.favorite.1981')}"
println "Favorite Movie (2012): ${getProjectProperty('movie.favorite.2012')}"
println "Favorite Movie (2013): ${getProjectProperty('movie.favorite.2013')}"
}

def String getProjectProperty(String propertyName)
{
String movieTitle = "null"
if (hasProperty(propertyName))
{
movieTitle = this.properties[propertyName]
}
return movieTitle
}

Some of the properties to be passed to this script will be provided on the command-line with -P, some will be provided on the command line with -D, one will be provided via environment variable, and two will be provided via gradle.properties file in the same directory as the build. That gradle.properties file is shown next.

gradle.properties


movie.favorite.2013=Star Trek into Darkness
systemProp.movie.favorite.2012=Skyfall

With the gradle.properties file in place, the other two interesting parts of the example are the setting of the environment variable. The example here is in DOS, but the same thing could be done with slightly different syntax in Linux environments. The DOS/Windows command is: set ORG_GRADLE_PROJECT.movie.favorite.1981="Raiders of the Lost Ark"

For this demonstration, I’ll run the Gradle build script with -D and -P parameters: gradle -b build-properties.gradle displayProperties -Pmovie.favorite.1996="Independence Day" -Dmovie.favorite.1997=Gattaca -Dorg.gradle.project.movie.favorite.1994="Shawshank Redemption"

When running the above-listed Gradle build script with the indicated gradle.properties file in place, with the indicated environment variable specified, and with the command just shown, the output looks that shown in the next screen snapshot.

The screen snapshot indicates how properties are seen/accessed in the Gradle build depending on their source and naming convention. In short, the output demonstrates the following “rules” of property availability in a Gradle build:

  • Command-line -P properties are “project properties”
  • Command-line -D properties are, with one exception, “system properties”
  • Command-line -D properties that begin with org.gradle.project. are “project properties”
  • Properties specified in gradle.properties are, with one exception, “project properties”
  • Properties specified in gradle.properties that begin with systemProp. are “system properties”
  • Properties specified via environment variable are, with one exception, “system properties”
  • Properties specified via environment variables that begin with ORG_GRADLE_PROJECT_ are “project properties”

Conclusion

Gradle provides numerous approaches for specifying properties that can be used to customize the Gradle build.

Original posting available at http://marxsoftware.blogspot.com/ (Inspired by Actual Events)

Continue reading

Posted in Gradle, Syndicated | Comments Off on Specifying Gradle Build Properties

The Gradle Interface: Gradle Build Metadata

As I’ve shown in previous posts such as “Identifying Gradle Conventions” and “Evolving Gradle Build from Ant Build: Importing Ant Build File”, significant information about a Gradle build can be gleaned by accessing Gradle’s APIs via Groovy. In this po… Continue reading

Posted in Gradle, Syndicated | Comments Off on The Gradle Interface: Gradle Build Metadata

Differentiating Ant Target-Based Gradle Tasks

In my blog post Evolving Gradle Build from Ant Build: Importing Ant Build File, I demonstrated using Gradle’s built-in AntBuilder-based Ant support to import Ant targets in a Gradle build. These Ant targets can then be accessed as Gradle tasks and appe… Continue reading

Posted in Gradle, Syndicated | Comments Off on Differentiating Ant Target-Based Gradle Tasks

Evolving Gradle Build from Ant Build: Importing Ant Build File

Changing the build system on a large project can be difficult and a lot of work. Fortunately for those migrating Ant builds to Gradle builds, Gradle provides particularly convenient mechanisms to facilitate this migration. Because Gradle is built on Gr… Continue reading

Posted in Ant, Gradle, Syndicated | Comments Off on Evolving Gradle Build from Ant Build: Importing Ant Build File

Identifying Gradle Conventions

Configuration by convention has many advantages, especially in terms of conciseness because developers do not need to explicitly configure things that are implicitly configured through convention. When taking advantage of configuration by convention, however, one needs to be aware of the conventions. These conventions might be documented, but I always like it when I can programmatically determine the conventions because documentation can become outdated (same principle behind code always being correct and comments only sometimes being correct). I begin this post by looking at how to identify the specific conventions associated with the Gradle Java Plugin. I then generalize this approach to identify all properties associated with all tasks associated with the root project of a Gradle build.

The Gradle documentation on Gradle Plugins states the following regarding the importance of Gradle Plugins and what they add to a Gradle build:

Gradle at its core intentionally provides little useful functionality for real world automation. All of the useful features, such as the ability to compile Java code for example, are added by plugins. Plugins add new tasks (e.g. JavaCompile), domain objects (e.g. SourceSet), conventions (e.g. main Java source is located at src/main/java) as well as extending core objects and objects from other plugins.

This post looks at some of the tasks, domain objects, and conventions that the Java Plugin brings to a Gradle build. To start, I need a very simple Gradle build file. It consists solely of a single line that applies the Java plugin. It is shown next in the Gradle build file build-java-plugin.gradle.

build-java-plugin.gradle


apply plugin: 'java'

With that single-line Gradle build file in place, it’s easy to see which Gradle tasks the plugin-provides by running the command gradle -b build-java-plugin.gradle tasks. The next two screen snapshots show the output of running an empty Gradle build file followed by the output of running the Gradle build file with only the application of the Java plugin.

By comparing the output from running Gradle “tasks” against an empty build file to the output from running Gradle “tasks” against the build file with the Java plugin applied, we can see that the Gradle has the same set of “Build Setup tasks” and “Help tasks” whether the plugin is applied or not. More significantly, we see that the Java plugin adds many new tasks categorized as “Build tasks” (assemble, build, buildDependents, buildNeeded, classes, clean, jar, testClasses), “Documentation tasks” (javadoc), “Verification tasks” (check, test), and “Rules”.

One feature I enjoy in Gradle 1.10 that Gradle 1.8 (the previous version I used) did not have is the ability on the command line to ask for details on a specific Gradle task. This is demonstrated in the next screen snapshot for Java Plugin tasks compileJava, jar, and javadoc. All three tasks have details written to standard output by using the help --task <task_name> command on the command line. These details on the Java Plugin tasks can also be found in the Gradle User Guide.

Because Gradle is built on Groovy, it’s fairly easy to determine characteristics of the Java Plugin using “brute force.” The next code listing, for build-java-plugin-properties.gradle, demonstrates using Groovy to determine the Gradle properties (those which can be specified with -P as opposed to system properties specified with -D) available to the build script before and after applying the Java plugin and then uses Groovy’s highly convenient overridden subtraction operator to find the differences. The names and values of all of the properties added to the Gradle script by the Java Plugin (except the property “properties”) are presented in alphabetical order.


// build-java-plugin-properties.gradle
//
// Displays properties that Gradle Java Plugin adds beyond properties already
// specified for any Gradle build.

def propertiesBefore = this.properties

apply plugin: 'java'

def propertiesAfter = this.properties

def extraProperties = propertiesAfter - propertiesBefore

def extraPropertiesKeys = new TreeSet<String>()
extraProperties.each
{ property ->
if (property.key != "properties")
{
extraPropertiesKeys.add(property.key)
}
}

extraPropertiesKeys.each
{ key ->
println "${key} : ${extraProperties.get(key)}"
}

The next image shows a screen snapshot with the output from running this script. The screen snapshot does not show the full output, but a larger piece of the output (all the properties) is shown in text after the image.

Output from Running Above Gradle Script to See Java Plugin Properties


apiDocTitle : gradleExample API
archivesBaseName : gradleExample
assemble : task ':assemble'
binaries : [classes 'main', classes 'test']
build : task ':build'
buildDependents : task ':buildDependents'
buildNeeded : task ':buildNeeded'
buildTasks : [build]
check : task ':check'
classes : task ':classes'
clean : task ':clean'
compileJava : task ':compileJava'
compileTestJava : task ':compileTestJava'
defaultArtifacts : org.gradle.api.internal.plugins.DefaultArtifactPublicationSet_Decorated@bc80d8
dependencyCacheDir : C:\java\examples\groovyExamples\gradleExample\build\dependency-cache
dependencyCacheDirName : dependency-cache
distsDir : C:\java\examples\groovyExamples\gradleExample\build\distributions
distsDirName : distributions
docsDir : C:\java\examples\groovyExamples\gradleExample\build\docs
docsDirName : docs
inheritedScope : org.gradle.api.internal.ExtensibleDynamicObject$InheritedDynamicObject@c10304
jar : task ':jar'
javadoc : task ':javadoc'
libsDir : C:\java\examples\groovyExamples\gradleExample\build\libs
libsDirName : libs
manifest : org.gradle.api.java.archives.internal.DefaultManifest@1ad3677
metaInf : []
module : org.gradle.api.internal.artifacts.ProjectBackedModule@d2eead
processResources : task ':processResources'
processTestResources : task ':processTestResources'
rebuildTasks : [clean, build]
reporting : org.gradle.api.reporting.ReportingExtension_Decorated@33ab8f
reportsDir : C:\java\examples\groovyExamples\gradleExample\build\reports
reportsDirName : reports
runtimeClasspath : file collection
sourceCompatibility : 1.7
sourceSets : [source set 'main', source set 'test']
sources : [[source set 'main:java', source set 'main:resources'], [source set 'test:java', source set 'test:resources']]
status : integration
targetCompatibility : 1.7
test : task ':test'
testClasses : task ':testClasses'
testReportDir : C:\java\examples\groovyExamples\gradleExample\build\reports\tests
testReportDirName : tests
testResultsDir : C:\java\examples\groovyExamples\gradleExample\build\test-results
testResultsDirName : test-results

Gradle makes it easy to see all the Gradle properties using the command “gradle properties“, but this command line action shows all properties regardless of their source (Gradle itself or a plugin).

Each Gradle task that the Java Plugin adds to the build has its own set of properties. These properties can be identified in the Gradle Build Language Reference. The Task Types section of that document has links to each task type. The linked-to pages on each task type have details on the properties supported by that task type. For example, the Task Type JavaCompile is listed on its page as having properties such as classpath, destinationDir, and source.

The following rather extensive script displays the settings for the properties of the compileJava, jar, and javadoc Gradle Java Plugin tasks. This script demonstrates how powerful it can be to apply Groovy to identifying Gradle build settings. The script could be shorter if more reflection was used, but calling the tasks’ properties out explicitly does have advantages in terms of readability and as a reference for what properties are available on each task.

build-java-plugin-metadata.gradle


// build-java-plugin-metadata.gradle
//
// Displays the properties associated with the Gradle Java Plugin tasks
// of "compileJava", "jar", and "javadoc".

import groovy.transform.Field

apply plugin: 'java'

@Field int MAX_COLUMNS = 80
@Field String headerSeparator = "=".multiply(MAX_COLUMNS)

printCompileJavaProperties()
printJarProperties()
printJavadocProperties()

def printCompileJavaProperties()
{
printHeader("compileJava Task")
println "compileJava.classpath:\n${extractStringRepresentation(compileJava.classpath)}"
println "compileJava.destinationDir:\n${extractStringRepresentation(compileJava.destinationDir)}"
println "compileJava.source:\n${extractStringRepresentation(compileJava.source)}"
println "compileJava.options:\n${extractStringRepresentation(compileJava.options)}"
println "compileJava.includes:\n${extractStringRepresentation(compileJava.includes)}"
println "compileJava.excludes:\n${extractStringRepresentation(compileJava.excludes)}"
println "compileJava.sourceCompatibility:\n${extractStringRepresentation(compileJava.sourceCompatibility)}"
println "compileJava.targetCompatibility:\n${extractStringRepresentation(compileJava.targetCompatibility)}"
}

def printJarProperties()
{
printHeader("jar Task")
println "jar.appendix:\n${extractStringRepresentation(jar.appendix)}"
println "jar.archiveName:\n${extractStringRepresentation(jar.archiveName)}"
println "jar.archivePath:\n${extractStringRepresentation(jar.archivePath)}"
println "jar.baseName:\n${extractStringRepresentation(jar.baseName)}"
println "jar.caseSensitive:\n${extractStringRepresentation(jar.caseSensitive)}"
println "jar.classifier:\n${extractStringRepresentation(jar.classifier)}"
println "jar.destinationDir:\n${extractStringRepresentation(jar.destinationDir)}"
println "jar.dirMode:\n${extractStringRepresentation(jar.dirMode)}"
println "jar.duplicatesStrategy:\n${extractStringRepresentation(jar.duplicatesStrategy)}"
println "jar.entryCompression:\n${extractStringRepresentation(jar.entryCompression)}"
println "jar.excludes:\n${extractStringRepresentation(jar.excludes)}"
println "jar.extension:\n${extractStringRepresentation(jar.extension)}"
println "jar.fileMode:\n${extractStringRepresentation(jar.fileMode)}"
println "jar.includeEmptyDirs:\n${extractStringRepresentation(jar.includeEmptyDirs)}"
println "jar.includes:\n${extractStringRepresentation(jar.includes)}"
println "jar.manifest:\n${extractStringRepresentation(jar.manifest)}"
println "jar.source:\n${extractStringRepresentation(jar.source)}"
println "jar.version:\n${extractStringRepresentation(jar.version)}"
}

def printJavadocProperties()
{
printHeader("javadoc Task")
println "javadoc.classpath:\n${extractStringRepresentation(javadoc.classpath)}"
println "javadoc.destinationDir:\n${extractStringRepresentation(javadoc.destinationDir)}"
println "javadoc.excludes:\n${extractStringRepresentation(javadoc.excludes)}"
println "javadoc.executable:\n${extractStringRepresentation(javadoc.executable)}"
println "javadoc.failOnError:\n${extractStringRepresentation(javadoc.failOnError)}"
println "javadoc.includes:\n${extractStringRepresentation(javadoc.includes)}"
println "javadoc.maxMemory:\n${extractStringRepresentation(javadoc.maxMemory)}"
println "javadoc.options:\n${extractStringRepresentation(javadoc.options)}"
println "javadoc.source:\n${extractStringRepresentation(javadoc.source)}"
println "javadoc.title:\n${extractStringRepresentation(javadoc.title)}"
}

def String extractStringRepresentation(Object object)
{
String returnString
if (object in String)
{
returnString = "\t${object}\n"
}
else if (object in File)
{
returnString = "\t${object.canonicalPath}\n"
}
else if (object in FileCollection) // FileTree is a FileCollection
{
StringBuilder filesStr = new StringBuilder()
def files = object.files
files.each
{ file ->
filesStr << "\t" << file.canonicalPath << "\n"
}
returnString = filesStr.toString()
}
else if (object in CompileOptions)
{
StringBuilder compileOptionsStr = new StringBuilder()
def compileProperties = object.properties
compileProperties.each
{ compileProperty ->
if (compileProperty.value in DebugOptions)
{
compileOptionsStr << "\t" << compileProperty.key << ": " << extractStringRepresentation(compileProperty.value) << "\n"
}
else if (compileProperty.value in DependOptions)
{
compileOptionsStr << "\t" << compileProperty.key << ": " << extractStringRepresentation(compileProperty.value) << "\n"
}
else if (compileProperty.value in ForkOptions)
{
compileOptionsStr << "\t" << compileProperty.key << ": " << extractStringRepresentation(compileProperty.value) << "\n"
}
else if (compileProperty.key != "class")
{
compileOptionsStr << "\t" << compileProperty.key << ": " << compileProperty.value << "\n"
}
}
returnString = compileOptionsStr.toString()
}
else if (object in DebugOptions)
{
returnString = "\t${object.debugLevel}"
}
else if (object in DependOptions)
{
returnString = "\t${object.classpath}"
}
else if (object in ForkOptions)
{
returnString = "\t${object.executable} executable with ${object.tempDir} temp directory"
}
else if (object in Set || object in Boolean || object in Number || object in Enum)
{
returnString = "\t${object.toString()}\n"
}
else if (object in Manifest)
{
StringBuilder manifestStr = new StringBuilder()
def manifestAttributes = object.getAttributes()
manifestAttributes.each
{ manifestAttribute ->
manifestStr << "\t" << manifestAttribute.key << ": " << manifestAttribute.value << "\n"
}
returnString = manifestStr.toString()
}
else if (object in MinimalJavadocOptions)
{
returnString = extractJavadocOptionsAsString(object)
}
else if (object == null)
{
returnString = "\tnull\n"
}
else
{
returnString = "\t${object?.class} was unexpected type.\n"
}
return returnString
}

def String extractJavadocOptionsAsString(MinimalJavadocOptions javadocOptions)
{
StringBuilder javadocOptionsStr = new StringBuilder()

javadocOptionsStr << "\tjavadoc.bootClasspath:"
def bootClasspathFiles = javadocOptions.bootClasspath
bootClasspathFiles.each
{ bootClasspathFile ->
javadocOptionsStr << "\t\t" << bootClasspathFile.canonicalName << "\n"
}
javadocOptionsStr << "\n"

javadocOptionsStr << "\tjavadocOptions.classpath:"
def classpathFiles = javadocOptions.classpath
classpathFiles.each
{ classpathFile ->
javadocOptionsStr << "\t\t" << classpathFile.canonicalName << "\n"
}
javadocOptionsStr << "\n"

javadocOptionsStr << "\tjavadocOptions.destinationDirectory: " << javadocOptions.destinationDirectory?.canonicalName << "\n"

javadocOptionsStr << "\tjavadocOptions.doclet: " << javadocOptions.doclet << "\n"

javadocOptionsStr << "\tjavadocOptions.docletpath:"
def docletpath = javadocOptions.docletpath
docletpath.each
{ docletEntry ->
javadocOptionsStr << "\t\t" << docletEntry.canonicalName << "\n"
}
javadocOptionsStr << "\n"

javadocOptionsStr << "\tjavadocOptions.encoding: " << javadocOptions.encoding << "\n"

javadocOptionsStr << "\tjavadocOptions.extDirs:"
def extDirs = javadocOptions.extDirs
extDirs.each
{ extDir ->
javadocOptionsStr << "\t\t" << extDir.canonicalName << "\n"
}
javadocOptionsStr << "\n"

javadocOptionsStr << "\tjavadocOptions.header: " << javadocOptions.header << "\n"

javadocOptionsStr << "\tjavadocOptions.JFlags:"
def jflags = javadocOptions.JFlags
jflags.each
{ jflag ->
javadocOptionsStr << "\t\t" << jflag << "\n"
}
javadocOptionsStr << "\n"

javadocOptionsStr << "\tjavadocOptions.locale: " << javadocOptions.locale << "\n"

javadocOptionsStr << "\tjavadocOptions.memberLevel: " << javadocOptions.memberLevel << "\n"

javadocOptionsStr << "\tjavadocOptions.optionFiles:"
def optionFiles = javadocOptions.optionFiles
optionFiles.each
{ optionFile ->
javadocOptionsStr << "\t\t" << optionFile.canonicalName << "\n"
}
javadocOptionsStr << "\n"

javadocOptionsStr << "\tjavadocOptions.outputLevel: " << javadocOptions.outputLevel << "\n"

javadocOptionsStr << "\tjavadocOptions.overview: " << javadocOptions.overview << "\n"

javadocOptionsStr << "\tjavadocOptions.source: " << javadocOptions.source << "\n"

javadocOptionsStr << "\tjavadocOptions.sourceNames:"
def sourceNames = javadocOptions.sourceNames
sourceNames.each
{ sourceName ->
javadocOptionsStr << "\t\t" << sourceName << "\n"
}
javadocOptionsStr << "\n"

javadocOptionsStr << "\tjavadocOptions.windowTitle: " << javadocOptions.windowTitle << "\n"

return javadocOptionsStr.toString()
}

def printHeader(String headerText)
{
println headerSeparator
println "= ${headerText.center(MAX_COLUMNS-4)} ="
println headerSeparator
}

I used the Groovy @Field annotation in this build file to make the variable to which it was applied available to methods in the build file. The @Field annotation was not available until Groovy 1.8 and this reminded me of something else significant to point out about Gradle and Groovy here: Gradle uses its own prepackaged Groovy rather than any other version of Groovy that might be installed on one’s machine. You can determine which version of Groovy that is with the gradle --version command. The next screen snapshot demonstrates that my version of Groovy (2.1.6) is different than the version of Groovy (1.8.6) used by my installation of Gradle (Gradle 1.10). Because Gradle 1.10 comes with Groovy 1.8.6, I had the @Field annotation at my disposal.

Because the output from the last script is so lengthy, I show it here as text rather than in an image.

Output of Running Gradle on build-java-plugin-metadata.gradle


================================================================================
= compileJava Task =
================================================================================
compileJava.classpath:

compileJava.destinationDir:
C:\java\examples\groovyExamples\gradleExample\build\classes\main

compileJava.source:
C:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\Main.java
C:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\Main2.java
C:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\Main3.java
C:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\Main4.java
C:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\Temperature.java
C:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\TemperatureScale.java
C:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\TemperatureUnit.java
C:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\TemperatureUnit2.java
C:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\TemperatureUnit3.java

compileJava.options:
bootClasspath: null
fork: false
encoding: null
deprecation: false
warnings: true
forkOptions: null executable with null temp directory
failOnError: true
useDepend: false
includeJavaRuntime: false
useAnt: false
compilerArgs: []
debug: true
extensionDirs: null
compiler: null
debugOptions: null
verbose: false
optimize: false
dependOptions:
listFiles: false

compileJava.includes:
[]

compileJava.excludes:
[]

compileJava.sourceCompatibility:
1.7

compileJava.targetCompatibility:
1.7

================================================================================
= jar Task =
================================================================================
jar.appendix:
null

jar.archiveName:
gradleExample.jar

jar.archivePath:
C:\java\examples\groovyExamples\gradleExample\build\libs\gradleExample.jar

jar.baseName:
gradleExample

jar.caseSensitive:
true

jar.classifier:


jar.destinationDir:
C:\java\examples\groovyExamples\gradleExample\build\libs

jar.dirMode:
null

jar.duplicatesStrategy:
INCLUDE

jar.entryCompression:
DEFLATED

jar.excludes:
[]

jar.extension:
jar

jar.fileMode:
null

jar.includeEmptyDirs:
true

jar.includes:
[]

jar.manifest:
Manifest-Version: 1.0

jar.source:
C:\java\examples\groovyExamples\gradleExample\build\tmp\jar\MANIFEST.MF

jar.version:
null

================================================================================
= javadoc Task =
================================================================================
javadoc.classpath:
C:\java\examples\groovyExamples\gradleExample\build\classes\main
C:\java\examples\groovyExamples\gradleExample\build\resources\main

javadoc.destinationDir:
C:\java\examples\groovyExamples\gradleExample\build\docs\javadoc

javadoc.excludes:
[]

javadoc.executable:
null

javadoc.failOnError:
true

javadoc.includes:
[]

javadoc.maxMemory:
null

javadoc.options:
javadoc.bootClasspath:
javadocOptions.classpath:
javadocOptions.destinationDirectory: null
javadocOptions.doclet: null
javadocOptions.docletpath:
javadocOptions.encoding: null
javadocOptions.extDirs:
javadocOptions.header: null
javadocOptions.JFlags:
javadocOptions.locale: null
javadocOptions.memberLevel: null
javadocOptions.optionFiles:
javadocOptions.outputLevel: QUIET
javadocOptions.overview: null
javadocOptions.source: null
javadocOptions.sourceNames:
javadocOptions.windowTitle: null

javadoc.source:
C:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\Main.java
C:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\Main2.java
C:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\Main3.java
C:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\Main4.java
C:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\Temperature.java
C:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\TemperatureScale.java
C:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\TemperatureUnit.java
C:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\TemperatureUnit2.java
C:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\TemperatureUnit3.java

javadoc.title:
gradleExample API

:help

Welcome to Gradle 1.10.

To run a build, run gradle ...

To see a list of available tasks, run gradle tasks

To see a list of command-line options, run gradle --help

BUILD SUCCESSFUL

Total time: 14.041 secs

The example shown above works well for identifying specific properties associated with the Java Gradle plugin. This works fine, but its limitations include the need to write explicit code for each property whose value is desired. This implies further limitations of not necessarily knowing all the properties that are available (I used the documentation to explicitly print out values in the example above). A further implied limitation is that the script above will not display any properties values that are added to those tasks in the future. The next Gradle build example is based on the previous example, but this example does not explicitly state the tasks and properties to display. Instead, it finds all Tasks associated with the root project and then prints all properties associated with each of those Tasks.

build-java-plugin-metadata-reflection.gradle


// build-java-plugin-metadata-reflection.gradle
//
// Displays the properties associated with the tasks associated with the Gradle
// root project.
//

import groovy.transform.Field

apply plugin: 'java'

@Field int MAX_COLUMNS = 80
@Field String headerSeparator = "=".multiply(MAX_COLUMNS)

def rootProject = getRootProject()
def tasks = rootProject.tasks
tasks.each
{ task ->
printTaskProperties(task)
}


def printTaskProperties(Task task)
{
printHeader("Task " + task.name)
def taskProperties = task.properties
taskProperties.each
{ taskProperty ->
println "${task.name}.${taskProperty.key}=${extractStringRepresentation(taskProperty.value)}"
}
}

def String extractStringRepresentation(Object object)
{
String returnString
if (object in String)
{
returnString = "\t${object}\n"
}
else if (object in File)
{
returnString = "\t${object.canonicalPath}\n"
}
else if (object in FileCollection) // FileTree is a FileCollection
{
StringBuilder filesStr = new StringBuilder()
def files = object.files
files.each
{ file ->
filesStr << "\t" << file.canonicalPath << "\n"
}
returnString = filesStr.toString()
}
else if (object in CompileOptions)
{
StringBuilder compileOptionsStr = new StringBuilder()
def compileProperties = object.properties
compileProperties.each
{ compileProperty ->
if (compileProperty.value in DebugOptions)
{
compileOptionsStr << "\t" << compileProperty.key << ": " << extractStringRepresentation(compileProperty.value) << "\n"
}
else if (compileProperty.value in DependOptions)
{
compileOptionsStr << "\t" << compileProperty.key << ": " << extractStringRepresentation(compileProperty.value) << "\n"
}
else if (compileProperty.value in ForkOptions)
{
compileOptionsStr << "\t" << compileProperty.key << ": " << extractStringRepresentation(compileProperty.value) << "\n"
}
else if (compileProperty.key != "class")
{
compileOptionsStr << "\t" << compileProperty.key << ": " << compileProperty.value << "\n"
}
}
returnString = compileOptionsStr.toString()
}
else if (object in DebugOptions)
{
returnString = "\t${object.debugLevel}"
}
else if (object in DependOptions)
{
returnString = "\t${object.classpath}"
}
else if (object in ForkOptions)
{
returnString = "\t${object.executable} executable with ${object.tempDir} temp directory"
}
else if (object in Set || object in List || object in Boolean || object in Number || object in Enum || object in Class)
{
returnString = "\t${object.toString()}\n"
}
else if (object in Manifest)
{
StringBuilder manifestStr = new StringBuilder()
def manifestAttributes = object.getAttributes()
manifestAttributes.each
{ manifestAttribute ->
manifestStr << "\t" << manifestAttribute.key << ": " << manifestAttribute.value << "\n"
}
returnString = manifestStr.toString()
}
else if (object in MinimalJavadocOptions)
{
returnString = extractJavadocOptionsAsString(object)
}
else if (object in Convention)
{
StringBuilder conventionStr = new StringBuilder()
object.plugins.each?.keyset
{ plugin ->
conventionStr << "\t" << plugin << "\n"
}
returnString = conventionStr.toString()
}
else if (object in LoggingManager)
{
returnString = "\n\tCurrent Log Level: ${object.level}\n\tStandard Error: ${object.standardErrorCaptureLevel}\n\tStandard Output: ${object.standardOutputCaptureLevel}\n"
}
else if (object == null)
{
returnString = "\tnull\n"
}
else
{
returnString = "\t${object?.class} was unexpected type with value of ${object}.\n"
}
return returnString
}

def String extractJavadocOptionsAsString(MinimalJavadocOptions javadocOptions)
{
StringBuilder javadocOptionsStr = new StringBuilder()

javadocOptionsStr << "\tjavadoc.bootClasspath:"
def bootClasspathFiles = javadocOptions.bootClasspath
bootClasspathFiles.each
{ bootClasspathFile ->
javadocOptionsStr << "\t\t" << bootClasspathFile.canonicalName << "\n"
}
javadocOptionsStr << "\n"

javadocOptionsStr << "\tjavadocOptions.classpath:"
def classpathFiles = javadocOptions.classpath
classpathFiles.each
{ classpathFile ->
javadocOptionsStr << "\t\t" << classpathFile.canonicalName << "\n"
}
javadocOptionsStr << "\n"

javadocOptionsStr << "\tjavadocOptions.destinationDirectory: " << javadocOptions.destinationDirectory?.canonicalName << "\n"

javadocOptionsStr << "\tjavadocOptions.doclet: " << javadocOptions.doclet << "\n"

javadocOptionsStr << "\tjavadocOptions.docletpath:"
def docletpath = javadocOptions.docletpath
docletpath.each
{ docletEntry ->
javadocOptionsStr << "\t\t" << docletEntry.canonicalName << "\n"
}
javadocOptionsStr << "\n"

javadocOptionsStr << "\tjavadocOptions.encoding: " << javadocOptions.encoding << "\n"

javadocOptionsStr << "\tjavadocOptions.extDirs:"
def extDirs = javadocOptions.extDirs
extDirs.each
{ extDir ->
javadocOptionsStr << "\t\t" << extDir.canonicalName << "\n"
}
javadocOptionsStr << "\n"

javadocOptionsStr << "\tjavadocOptions.header: " << javadocOptions.header << "\n"

javadocOptionsStr << "\tjavadocOptions.JFlags:"
def jflags = javadocOptions.JFlags
jflags.each
{ jflag ->
javadocOptionsStr << "\t\t" << jflag << "\n"
}
javadocOptionsStr << "\n"

javadocOptionsStr << "\tjavadocOptions.locale: " << javadocOptions.locale << "\n"

javadocOptionsStr << "\tjavadocOptions.memberLevel: " << javadocOptions.memberLevel << "\n"

javadocOptionsStr << "\tjavadocOptions.optionFiles:"
def optionFiles = javadocOptions.optionFiles
optionFiles.each
{ optionFile ->
javadocOptionsStr << "\t\t" << optionFile.canonicalName << "\n"
}
javadocOptionsStr << "\n"

javadocOptionsStr << "\tjavadocOptions.outputLevel: " << javadocOptions.outputLevel << "\n"

javadocOptionsStr << "\tjavadocOptions.overview: " << javadocOptions.overview << "\n"

javadocOptionsStr << "\tjavadocOptions.source: " << javadocOptions.source << "\n"

javadocOptionsStr << "\tjavadocOptions.sourceNames:"
def sourceNames = javadocOptions.sourceNames
sourceNames.each
{ sourceName ->
javadocOptionsStr << "\t\t" << sourceName << "\n"
}
javadocOptionsStr << "\n"

javadocOptionsStr << "\tjavadocOptions.windowTitle: " << javadocOptions.windowTitle << "\n"

return javadocOptionsStr.toString()
}

def printHeader(String headerText)
{
println headerSeparator
println "= ${headerText.center(MAX_COLUMNS-4)} ="
println headerSeparator
}

Because this output is for all properties associated with all Tasks associated with the Gradle build’s root project, the output is too lengthy to include here. Not all of the property value instances have classes that the extractStringRepresentation(Object object) method is prepared to handle, but those cases could be added to the if-else if structure of that method to handle them. This version of the Gradle build is more generic than the earlier one and prints out properties associated with Tasks that are grouped by Task.

Because a Gradle build is tightly coupled to Groovy, Groovy syntax and features can be used to learn more about the Gradle build. The examples in this post took advantage of numerous Groovy niceties. The reason that the Gradle build code above is so verbose is because most of the Gradle classes used for property values do NOT have overridden toString() methods and so no really useful output is shown without special code to call specific methods to get useful representations. I didn’t do it in this post’s examples, but another option to deal with lack of overridden toString() methods would be to use Groovy’s interception capabilities (metaClass.invokeMethod) to intercept calls to toString() and provide an overridden version. That would be essentially the same code as used above, but would be encapsulated in the intercepting objects rather than contained in the script code.

Conclusion

Gradle has really nice documentation (especially the Gradle User Guide and the Gradle Build Language Reference) and most of the tasks and properties associated with the Java Plugin for Gradle (and other plugins) are easily accessible from that documentation. However, I like to know how to programmatically identify important conventions in case the documentation is ever mistaken or I use a version different than the documentation supports. Another objective of this post has been to demonstrate how useful it can be to know Groovy when working with Gradle. It is for this reason that I believe that the rising prominence of Gradle cannot help but increase interest in Groovy.

Original posting available at http://marxsoftware.blogspot.com/ (Inspired by Actual Events)

Continue reading

Posted in Gradle, Groovy, Syndicated | Comments Off on Identifying Gradle Conventions

Significant Software Development Developments of 2013

At the end of each calendar year, I like to summarize some of the most significant developments in the software development industry that happened during the year that is ending. The choice of these is entirely subjective and obviously colored by my own experience, background, perceptions, and preferences. Not worrying about the opinionated content of such a post, I now present the developments in software development that I consider most significant in 2013.

10. Gradle

Gradle appeared to me to enter the mainstream consciousness of software developers in a big way in 2013. I have been watching Gradle’s development and playing with it a bit for some time now, but I have noticed that numerous open source projects now mention it prominently, it’s referenced in many recently published Java books that aren’t even about Gradle specifically, and Google selected Gradle to be delivered with its Android Studio product announced at Google I/O 2013. It took a while for Maven to breakthrough and compete with Ant and I think 2013 is seeing the beginning of Gradle’s breakthrough to challenge Maven and Ant for predominance in Java-based build systems. Three books devoted to Gradle (the short Gradle: Beyond the Basics, the more comprehensive Gradle in Action, and the German Gradle: Modernes Build-Management – Grundlagen und Praxiseinsatz) have listed 2013 publication dates.

Gradle‘s rapidly rising popularity is nearly matched by its torrid rate of new releases. Gradle 1.4 (“faster builds that use less heap space”), Gradle 1.5 (“optimizations to dependency resolution”), Gradle 1.6 (improved Task ordering, “JaCoCo plugin for test coverage,” and support for JUnit test categories), Gradle 1.7 (“fastest Gradle ever”), Gradle 1.8 (performance improvements and more native languages support), Gradle 1.9 (bug fixes and HTML dependency report), and Gradle 1.10 (“command-line usability features”) were all released in 2013.

Gradle’s success does not surprise me. It’s Groovy foundation alone offers numerous advantages: Groovy scripts are easier to write procedural build-style code than is XML, Groovy has numerous syntactic shortcuts, Groovy is easily learned and applied by Java developers, Groovy has full JVM access, and Groovy includes built-in Ant support. On top of its inherent advantages from being built on Groovy, Gradle builds many useful and attractive features of its own on top of that Groovy foundation. Gradle adheres to several Ant and Maven conventions and supports Ivy and Maven repositories, making it straightforward to move from Maven or Ant+Ivy to Gradle.

Ruby on Rails helped bring Ruby into mainstream international prominence and, to a lesser degree, Grails helped do the same thing for Groovy. Gradle has the potential to pick up where Grails left off and push Groovy even further into the spotlight.

9. Trend Toward Single Language Development

For several years now, there has been a definite trend toward polyglot programming (polyglot persistence was even on last year’s version of this post). Although this trend is likely to continue because some languages are better for scripting than others, some languages are better suited for web development than others, some languages are better suited for desktop development than others, some languages are better suited for realtime and embedded device development than others, some languages are better suited for scientific computing than others, and so on. However, I have seen indications of the pendulum swinging back at least a bit recently.

One of the arguments in favor of Node.js is the ability for JavaScript developers to use the same language on the “front-end” of a web application as on the “back-end.” In the post Top Things I learned about development in 2013, Antonin Januska writes, “Working back to front in the same language is awesome.” This is, of course, the reason that Java developers have in some cases been resistant to using JavaScript, Flex, or JavaFX Script (now deprecated) for front-ends of their Java applications (and why tools like Google Web Toolkit have been so popular). Java developers who write desktop applications (yes Virginia, desktop applications do exist) often experience the advantages of using the same language front-to-back as well.

One of Ceylon‘s most promising possibilities is the ability to write code in Ceylon that works on both Java Virtual Machines and JavaScript virtual machines and so could be used front-to-back in a Ceylon-based application. Indeed, the Ceylon page advertises, “[Ceylon] runs on both Java and JavaScript virtual machines, bridging the gap between client and server.” Languages commonly associated with the Java Virtual Machine such as Scala and Kotlin also are offering the ability to compile to JavaScript.

A final example of the trend back to a single language in many environments is the use of Python in scientific computing as covered in the post The homogenization of scientific computing, or why Python is steadily eating other languages’ lunch.

I’m not arguing that this trend means that there will only be one main programming language in the future. However, I do believe it is generally human nature to want to use the same language or approach as much as possible because it’s what we’re familiar with and using the same language helps us to leverage our experience more broadly in the same application. The trend seems to be for each of the major languages (C/C++, Java, JavaScript, Python, .NET languages, etc.) to continue building up their own “stack” to support end-to-end functionality within that language and its ecosystem of frameworks, libraries, and tools. It’s no coincidence that once a new language starts to see significant adoption, it quickly begins to see development of a variety of frameworks, libraries, and toolkits that extend the reach of that language.

I also don’t want to imply that this is the end of polyglot programming. I don’t see any programming language that is the best fit in all cases and there is no doubt that the most valuable developers will be those familiar with more than one programming language.

8. Internet of Things

I first heard about the concept of the Internet of Things at JavaOne 2012 and it got even more attention at JavaOne 2013. Oracle is not the only company touting the Internet of Things. IBM is into the Internet of Things as are many others.

Some believe that 2014 will be the year of the Internet of Things. Tori Wieldt has called “Java and the Internet of Things” one of the “Top Java Stories of 2013.” In 2013, two series in Hinkmond Wong’s Weblog have focused on the Internet of Things with featured posts on a Thanksgiving Turkey Tweeter and on a Christmas Santa Detector.

Other useful articles with differing opinions on the Internet of Things include The Internet of Things: a tangled web, Here’s the Scariest Part of the Internet of Things, The Internet Of Things Will Be Huge—Just Not As Huge As The Hype, Five Challenges For The Internet of Things Ecosystem, The Internet of things will not arrive in 2014, CES 2013: The Break-Out Year For The Internet Of Things, and Here’s Why ‘The Internet Of Things’ Will Be Huge, And Drive Tremendous Value For People And Businesses.

On a lighter (or more dire, depending on your perspective) note related to The Internet of Things, Aaron Pressman writes, “The whole crazy ‘Internet of Things’ movement to put everything under network control seems tailor made for Hal” (2001: A Space Odyssey).

7. Mobile Development

If someone not familiar with our industry was to start reading our software development social media sites and forums, that person would likely come to the conclusion that the vast majority of software development today is development of mobile applications. I have long argued that blog posts and articles often skew toward more leading-edge topics than established topics for a variety of reasons (perception/reality that established topics are already well-covered, resume building, fun to play with and write about new things, etc.). That being stated, there is no question that mobile development is popular in reality and not just in perception. There is no question that a big part of HTML5’s popularity and rapid adoption is the opportunity to write applications in one set of languages (HTML/JavaScript/CSS) that will run on multiple mobile devices. Numerous projects and tools are being released to allow for writing applications in one language and compiling them to native formats for various mobile devices.

6. Responsive Design

At the end of 2012, Pete Cashmore predicted that 2013 would be the “Year of Responsive Web Design” because of its “obvious benefits”: “You build a website once, and it works seamlessly across thousands of different screens.” I like Jordan Larkin‘s explanation of responsive web design:

The term “responsive web design” (or responsive mobile design) refers to websites that change and adapt their appearance for optimum viewing on all screen sizes, tablets, smartphones, ipods, kindles along with desktop and laptop computer screens. Occasionally, in the digital arts industry, it is called “fluid design”, “adaptive website design” or “RWD”. Unresponsive websites do not change to fit different screen sizes, which means they can be difficult to navigate and look at on smaller devices.

As a person who is using a smartphone for an increasing percentage of my daily online activities, but still uses the laptop frequently and the desktop occasionally, I am appreciating firsthand the web site authors whose web sites and pages work well on all of these devices. It’s often satisfactory to have two different web sites (one for mobile devices and one for everything else) from a consumer point of view, but this obviously means essentially duplicate code for the site developers. Even from a consumer point of view, there are times when I find the mobile version of a site lacking in features and in those cases it’d be preferable to have the regular site on all devices as long as that regular site appeared nicely on all devices.

The highly informative web site A List Apart has a nice set of articles related to responsive web design.

5. Node.js

JavaScript, despite its flaws, has dominated the web browser for years. Although JavaScript on the server has been available for some time (such as with Rhino and more recently Nashorn in Java), Node.js seems to be doing for JavaScript on the server what Ruby on Rails did for Ruby: the framework is popularizing the language (or in this case, popularizing the language specifically on the server).

2013 has been a big year for Node.js. There are numerous blogs and articles written on it on seemingly a daily basis. Some of these articles include What You Need To Know About Node.js and Node.js keeps stealing Rails’ thunder.

Several books on Node.js have been published in 2013. These include Node.js in Action, Learning Node.js: A Hands-On Guide to Building Web Applications in JavaScript, Node.js the Right Way: Practical, Server-Side JavaScript That Scales, Pro Node.js for Developers, Node.js Recipes: A Problem-Solution Approach, Mastering Node.js, Using Node.js for UI Testing, JavaScript on the Server Using Node.js and Express, and the final version of The Node Beginner Book.

4. Big Data

Big Data holds the same #4 spot on my list as it did last year. Apache Hadoop and the R Project are just two examples of popular products/languages riding the Big Data wave. Python too, is increasingly being chosen as the programming language of choice for working with big data sets.

Readers of java.net recently answered a survey regarding Big Data in which the closest thing to a consensus seemed to be that “Big Data Is Probably Significant, but not too Surprising.”

3. HTML5

HTML5 saw initial hype, disappointed for a while, and seems to be back on its rapid rise in popularity. I don’t call out JavaScript individually in this post, but group it with HTML and CSS as part of HTML5 (and its also grouped with Node.js in this post). Given that HTML5, for purposes of this blog post, represents all of these things, it easily makes my top three significant software development developments in 2013. As mentioned previously with regard to mobile development, HTML5 is a popular approach for generating applications once that can theoretically run on any mobile device.

HTML5 features are seeing increasing standardization in terms of implementations in major browser. JavaScript/HTML libraries such as Angular.js and Ember.js are building on the momentum that jQuery has brought to HTML5 development in recent years.

HTML5’s success is even evident in languages not considered part of HTML5 themselves. For example, one of the most heavily advertised new features of Java EE 7 is its HTML5 support. Recent versions of NetBeans IDE (considered primarily a Java IDE despite its multiple language support) have also seemed to emphasize HTML5 among their most important new features in 2013.

2. Security

As more information is online and we depend increasingly on availability of our data online, security continues to be an important issue for software developers. The trend of highly visibility security incidents continued in 2013. These incidents affected Ruby on Rails, Java, and other languages. The increasing frequency of security patches led Oracle to change how it labels the versions of Java SE.

An early 2013 article, Safeguard your code: 17 security tips for developers, outlines tips developers can take to improve the security of their applications. An earlier article in 2013 spelled out the increasing security concerns companies face. The book Java Coding Guidelines: 75 Recommendations for Reliable and Secure Programs has also been published in 2013. The 10 Biggest Security Stories Of 2013 outlines some of the biggest security-related stories of 2013.

1. Technical Dysfunction

Sadly, from a software development perspective, 2013 may be most remembered for the high profile technical glitches that occurred. Words like “debacle,” “disaster,” and “meltdown” have been associated with these issues and, rightly or wrongly, have reflected poorly on our industry. The most high profile dysfunction has been the embarrassing United States healthcare site healthcare.org. However, the issues that affect reputations and customer confidence have not been limited to government. Wal-Mart and Target, two major retailers in the United States, have had notable web site issues in the latter part of 2013 as well. Cloud-impacting technical dysfunction has occurred in 2013 in several notable cases including Amazon Web Services (AWS) and Google (including the search engine).

There seems to be plenty of blame to go around, but it seems difficult to get a good read on exactly what has caused these high profile technical failures. With healthcare.org, for example, I’ve seen people blame all types of different culprits including not allotting enough time to the effort, not being agile enough, being too agile, failing for despite agile approaches, failing to estimate user load correctly, getting government involved, etc. Although the real reasons are probably multiple and varied in nature and probably interest software developers more than others, the perception of our industry has gotten dinged up in 2013.

Honorable Mention

Although the developments in software development listed below did not make my top ten, they are significant enough to me to make this “Honorable Mention” category (in no particular or implied order).

JSON

One of the benefits of XML many years now has been the ubiquity of XML support across different languages, tools, frameworks, and libraries. For example, I recently wrote about how easy it is to use Groovy to search Subversion logs because Subversion makes its log output available in XML format and Groovy knows XML well.

JSON has been very popular with developers for some time now, but there have been many cases where standard libraries and tools that supported XML did not support JSON, meaning that developers had to write custom writing/reading code for JSON when using those libraries and tools. I’m beginning to see a lot more JSON support with tools and libraries now. Programming languages are also providing nice JSON parsing/writing capabilities. For example, Groovy has had JSON support for some time and Java EE 7 (JAX-RS 2.0) includes JSON support via the Java API for JSON.

JSON has been prominent enough in 2013 to warrant being included in titles of two Packt Publishing books published in 2013: JavaScript and JSON Essentials and Developing RESTful Services with JAX-RS 2.0, WebSockets, and JSON.

Java EE 7 Released

Java EE 7 was officially released in 2013. In a testament to Java EE’s current widespread use and expected potential use of Java EE 7, book publishers have already published several books on Java EE 7 including Java EE 7 First Look, Java EE 7 Essentials, Beginning Java EE 7, Java EE 7 Recipes: A Problem-Solution Approach, Introducing Java EE 7: A Look at What’s New, and Java EE 7 Developer Handbook.

Although I’ve never embraced JavaServer Faces (JSF), the feature of Java EE 7 that has been most interesting to me is the support for Faces Flows. I first read about this feature when reviewing Java EE 7 First Look and Neil Griffin‘s post Three Cheers for JSF 2.2 Faces Flows have reinforced my interest in this feature. In the post A Realistic JSF 2.2 Faces Flows Example, Reza Rahman supports my opinion that this is a key feature in Java EE 7 to watch with the quote, “Faces Flows are one of the best hidden gems in Java EE 7.” Michael and Faces Flows might persuade me to give JavaServer Faces another look.

A recent blog post shows integration of AngularJS with Java EE 7.

Single Page Applications

The advantage of web applications over desktop applications has always been significant easier deployment of web applications than of desktop applications. The cost, however, has been a less fluid experience and sometimes less performing application than could be provided on the desktop. The concept of single-page applications is to make web (and by extension mobile applications that use traditional web technologies) feel and behave more like a “single-page” desktop application. Newer JavaScript libraries such as Meteor are being designed for the “thicker client” style of single-page applications.

The Wikipedia page on Single Page Application lists some technical approaches to implementing this concept. The Manning book Single Page Web Applications was also released in 2013. It’s subtitle is “JavaScript end-to-end” (another piece of evidence of the general movement toward a single language).

See the description of Meteor below for another nice explanation of how web development is moving toward what is essentially this concept of single-page applications.

AngularJS

It seems like one cannot read any software development social media sites without running across mention of AngularJS. Although its Google roots are undoubtedly part of its success, AngularJS enjoys success from cleanly addressing significant needs in HTML/JavaScript development (shifting appropriate dynamic functionality from pure JavaScript to HTML with clever binding). In his post 10 Reasons Why You Should Use AngularJS, Dmitri Lau states that “Angular is the only framework that doesn’t make MVC seem like putting lipstick on a pig.” Jesus Rodriguez, in his post Why Does Angular.js Rock?, writes that AngularJS “excels in the creation of single-page-applications or even for adding some ‘magic’ to our classic web applications.” K. Scott Allen writes in his post Why Use AngularJS?, “I like Angular because I have fun writing code on top of the framework, and the framework doesn’t get in the way.”

Ember.js

Ember.js is another JavaScript library seeing significant online coverage in 2013. Ember 1.0 was released on 31 August 2013 and Ember 1.2.0 was released on 4 December 2013.

Like AngularJS and Knockout, Ember.js‘s approach is to embrace HTML and CSS rather than trying to abstract them away.

Famo.us

The famo.us web page currently requires one to “sign up for the beta” before being able to “experience famo.us.” It’s subtitle is “a JavaScript engine and framework that solve HTML5 performance.” Another famo.us page states, “famo.us is a front end framework that solves performance for HTML5 apps” and “works for phones, tablets, computers and television.”

Famo.us is discussed in two late 2013 InfoWorld posts: Did these guys just reinvent the Web? and Fast and flashy: Famo.us JavaScript framework revealed.

At this point, famo.us is still in beta, but it could be big in 2014 if it is able to deliver on what is advertised in 2013.

Meteor

Meteor is described on its main page as “an open source platform” for writing “an entire app in pure JavaScript” and using the “same APIs … on the client and the server.” In the Paul Krill interview Meteor aims to make JavaScript programming fun again, Matt DeBergalis stated that Meteor was created to address the changing web development paradigm often referred to as single-page application:

There is a shift in the Web application platform, and specifically, people are starting to write a new kind of application, what we call a thick client, where most of the code is actually running inside the Web browser itself rather than in a data center. This is an architectural change from running the software in the data center and sending HTML on the wire to a model where we have data on the wire and the actual rendering, the displaying of the user interface, is happening on the client. … That’s why it feels more interactive. It’s not page-based like the old Web. It’s much more engaging.”

MEAN Stack

Having a witty acronym helped advertise and communicate the LAMP stack (Linux, Apache HTTP Server, MySQL/MariaDB, PHP/Perl/Python) and arguably contributed to the adoption of this combination of technologies. With this in mind, I found Valeri Karpov‘s post The MEAN Stack: MongoDB, ExpressJS, AngularJS and Node.js interesting. The post’s author is another who points out the productivity advantages that can be gained from using a single language throughout an application. There is already a book underway: Getting MEAN with Mongo, Express, Angular, and Node. It will be interesting to watch this newly minted terminology and see if the stack and its name come close to the success that the LAMP stack and its name have enjoyed.

Commercial Support Dropped for GlassFish 4

Although it took longer to happen than most people probably anticipated, Oracle’s dropping of commercial support for GlassFish 4 was formally announced in 2013 and is what most of us expected when we heard of Oracle purchasing Sun. The future of GlassFish is certainly cloudier now and expectations for GlassFish’s future range from it being essentially dead to it thriving as the reference implementation.

Java IDEs

The major Java IDEs continued to add features to their already impressive feature sets in 2013. NetBeans had two major releases in 2013 with 7.3 released in February and 7.4 released in October. These two NetBeans releases added features such as Java EE 7 support, Project Easel for HTML5 development, Groovy 2.0 integration, JSON support, support for new JavaScript libraries (including Angular.js), native Java application packaging, Cordova integration, and improved support for non-JVM languages C/C++ and PHP.

IntelliJ IDEA 13 was released earlier this month. The release announcement highlights support for Java EE 7, improved Spring Framework integration, improved Android support thanks to IntelliJ IDEA Community Edition being used as the basis for Android Studio, improved database handling, and “refined Gradle support.” Eclipse is often the IDE chosen for building a more specialized IDE such as Spring IDE (Spring Tool Suite), Scala IDE, or the new Ceylon IDE, so it’s a particularly big deal that Google chose IntelliJ IDEA as the basis of its Android Studio.

Speaking of Eclipse, the seemingly most used Java-based IDE (especially when you consider the IDEs derived from it or based on it) also saw new releases in 2013. Eclipse 4.3 (Kepler) was released in 2013. There were also numerous popular plugins for Eclipse released in 2013.

Visual Studio 2013

Sun Microsystems was not the only company that saw desirable advantages and benefits from a single language that could be used at all layers of an application. Microsoft has implemented various efforts (Silverlight) for years to do the same thing. In 2013, Visual Studio 2013 was released with significant enhancements. These enhancements included improved support for languages not specific to Microsoft’s .NET framework. Many of these better supported languages are on my list in this post: JavaScript, HTML, CSS, and Python.

Groovy

Groovy’s 2.0 release (including static compilation support) made 2012 a big year for Groovy. Although 2013 did not see as significant of enhancements in the Groovy language, the year did start out with the announcement of Groovy 2.1. Perhaps the biggest part of that 2.1 release was Groovy’s full incorporation of Java SE 7‘s invokedynamic, a major Java SE enhancement intended for non-Java languages like Groovy.

Groovy 2.2’s release was announced toward the end of 2013. This release improved Groovy’s invokedynamic support by adding OSGi manifests to the Groovy’s invokedynamic-based JARs.

In The Groovy Conundrum, Andrew Binstock writes that “with the performance issues behind it, Groovy is a language primed for widespread use,” but warns that Groovy is a language that is “easy to learn, but hard to master.”

As is mentioned more than once in this post, Groovy has had a lot of additional exposure in 2013 thanks to Gradle’s rapidly rising popularity. I believe that Gradle will continue to introduce Groovy to developers not familiar with Groovy or will motivate developers who have not looked at Groovy for some time to look at it again.

Scala

It seems to me that Scala continues to gain popularity among Java developers. I continue to see Scala enthusiasts gushing about Scala on various Java and JVM blog comments and forums. One piece of evidence of Scala’s continuing and increasing popularity is the number of new books published in 2013 with Scala in their title. These include Scala in Action, Scala Cookbook: Recipes for Object-Oriented and Functional Programming, Functional Programming Patterns in Scala and Clojure: Write Lean Programs for the JVM, Scala Design Patterns: Patterns for Practical Reuse and Design, Play for Scala, Scala Object-Oriented Programming, and Getting Started with SBT for Scala.

For a much better background on what made 2013 a big year for Scala, see Jan Machacek‘s This Year in Scala (2013).

Ceylon

November 2013 saw “the first production release of the Ceylon language specification, compiler, and IDE.” This announcement, available online at Ceylon 1.0.0 is now available, also states, “Ceylon 1.0 is a modern, modular, statically typed programming language for the Java and JavaScript virtual machines.” Ceylon offers an Elipse-based IDE and has a formal specification. One of the factors favoring a successful future for Ceylon is its Red Hat sponsorship.

Kotlin

Kotlin is another language that compiles to the Java Virtual Machine or to a JavaScript virtual machine. It also has a strong sponsor in the world of Java in JetBrains, the company behind IntelliJ IDEA. 2013 saw several new releases of Kotlin: Kotlin M5.1, Kotlin M6, Kotlin M6.1, and Kotlin M6.2. I found the blog post Programming Android with Kotlin interesting because it demonstrates use of Kotlin and Gradle to build an Android application.

Go

The Go programming language has had strong backing from Google and continues to receive significant online coverage. Go 1.1 and Go 1.2 (with apparently improved performance) were both released in 2013. Of special interest to me is Go’s advertised source code backwards compatibility for all versions 1.x.

Camel

2013 was a big year for Apache Camel, the tool that “empowers you to define routing and mediation rules in a variety of domain-specific languages.” Camel-related developments in 2013 included the release of 2.11.0, release of 2.12.0, and release of 2.12.2. These frequent releases and the addition of a new committer and PMC member are among the signs of a healthy open source project.

The release of the Camel Essential Components (DZone Refcardz #170) kicked off 2013 for Camel. Camel got increased attention on software development social media sites in 2013. Zemian Deng‘s Getting started with Apache Camel using Java was syndicated on Java Code Geeks (as was his Apache Camel using Groovy Introduction) and Niraj Singh‘s Introduction to Apache Camel was also syndicated on Java Code Geeks. AndrejV‘s entire blog Just Did Some Code has so far (5 posts in 2013) been devoted to coverage of Camel!

Spring Boot

It’s still early to tell because Spring Boot is currently only at version 0.5, but Spring Boot has potential to be be widely adopted and used in the future. It looks like Spring Boot is inspired by and takes advantage of some of the best ideas in Ruby on Rails and Groovy and applies them to easy generation of Spring Framework-based applications.

Python

As stated earlier, Big Data is big and Python is getting a share of that Big Data action. The Continuum Analytics post Python for Big Data states, “Python is a powerful, flexible, open-source language that is easy to learn, easy to use, and has powerful libraries for data manipulation and analysis. … Python has a unique combination of being both a capable general-purpose programming language as well as being easy to use for analytical and quantitative computing.” Tal Yarkoni echoes this statement and observes that his “scientific computing toolbox been steadily homogenizing” on Python.

Python 3.3.1, Python 3.3.2, and Python 3.3.3 were all released in 2013. Cython has joined Pyrex as an alternative for easily writing C extensions with Python syntax and there is even a book on Learning Cython Programming.

The article Python 3.4.0 goes to beta with slew of new modules talks about some of the new features coming with Python 3.4.0 (beta) such as a standard enumeration construct. The article also points out that one of the biggest frustrations with Python remains: the two versions of the language (2.x and 3.x) and no easy route from 2.x to 3.x. From a Java development perspective, I find this interesting because there was a time when arguments like Bruce Eckel‘s (“People who don’t want to deal with these changes don’t upgrade, and those people tend not to upgrade anyway”) seemed logical and sensible. However, it’s not quite as easy as it sounds, particularly when one starts to realize the impact of this on the entire set of products, libraries, and frameworks written for a language that can be heavily impacted and perhaps not usable for some time if ever with the new language.

PHP and HHVM

2013 saw the formal release of the PHP 5.5.x versions: PHP 5.5.0, PHP 5.5.1, PHP 5.5.2, PHP 5.5.3, PHP 5.5.4, PHP 5.5.5, PHP 5.5.6, and PHP 5.5.7.

At the beginning of 2013, Gabriel Manricks outlined reasons Why 2013 is the Year of PHP. Specifically Manricks described tools such as Laravel (including Eloquent ORM), Composer (dependency manager, including Packagist), and PHPUnit (test-driven development in PHP).

The Facebook project HHVM (HipHop Virtual Machine for PHP) was initially released in 2010, but seemed to see a lot more attention in 2013. The original HPHPc compiler compiled PHP into C++ and was another manifestation of the drive to use a single language for authoring an application even if its compiled form was different. The availability of the open source HipHop Virtual Machine (HHVM) for PHP should help address performance issues with PHP; that is seemingly Facebook’s primary reason for developing it.

Android Studio

Android Studio was announced at Google I/O 2013 as “a new IDE that’s built with the needs of Android developers in mind” that is “based on the powerful, extensible IntelliJ IDEA Community Edition.”

Cloud Computing

Interest in cloud computing remained strong and continued to grow rapidly in 2013. Many of the other items discussed in this post (Big Data, security, technical dysfunctions, etc.) have strong relationships to cloud computing. For more on the biggest cloud stories on 2013, see The 10 Biggest Cloud Stories Of 2013.

Internet Explorer 11

I have not used Internet Explorer except when forced to for a number of years. For a long time, I used Firefox almost exclusively and in recent years I’ve used Google Chrome almost exclusively on PCs and Firefox on Linux. When I have been forced by a particular web site to use Internet Explorer, I have done reluctantly and am reminded of the much slower performance of the browser than I’m used to in terms of startup and even navigation. I have noticed over this Christmas break, however, when I had to install Internet Explorer 11 manually because the automatic process kept failing, that it’s a lot faster than even Internet Explorer 10 was. I still won’t make it my primary browser, but it’s nice that it performs much better when I do need to use it (such as to play Atari Arcade games without advertisements).

Internet Explorer 11 offers advantages for developers as well as users of the browser. Advertised benefits for developers (and by extension for users of these developers’ applications) are improved standards compatibility, new F12 developer tools,

It’s not all positive for Internet Explorer 11. Some people seem to want to downgrade to Explorer 10 and reportedly Internet Explorer 11 is presenting some problems for users of Microsoft’s own CRM application (after earlier reportedly breaking Google and Outlook access).

It surprises me a bit that the main Microsoft IE URL (http://windows.microsoft.com/en-us/internet-explorer/download-ie) referenced by the Internet Explorer 11 Guide for Developers still advertises downloading of Internet Explorer 9, a version of that browser that Google has already stated they will no longer support.

Windows 8 Not As Successful

Windows 8 seems to be experiencing similar disappointment after Windows 7 that Windows Vista experienced after Windows XP. In fact, The 10 Biggest Software Stories Of 2013 states, “So it looks like Windows 7 will become the new Windows XP — better get those downgrade rights ready.”

Raspberry Pi

The Raspberry Pi continues to catch a lot of interest (2 million had been sold as of October of this year). There were seemingly endless posts on how to do a wide variety of things with the Raspberry Pi. Some of these that stood out most to me are Premium Mathematica software free on budget Raspberry Pi, GertDuino: An Arduino for Your Raspberry Pi, How an open-source computer kit for kids based on Raspberry Pi is taking over Kickstarter, Running OpenJFX on Raspberry Pi, and Simon Ritter: Do You Like Coffee with Your dessert? Java and the Raspberry Pi.

DevOps

The 10 Biggest Software Stories Of 2013 points out that “Cisco, Google and VMware last year invested in Puppet Labs” and that “another DevOps player, Opscode, raised $32 million and changed its name to Chef, the name of its flagship product.”

Twitter Bootstrap

Bootstrap (alternatively known as Twitter Bootstrap and Twitter Blueprint) has become so popular and prevalent that there is now a popular (one of DZone’s top posts in 2013)

post stating Please stop using Twitter Bootstrap. In August 2013, two years after the public release of Bootstrap, Bootstrap 3 was released (with 3.0.3 released in December). Everybody Should Code

The conversation of whether everybody should or code write code and develop software continued in 2013. Jessica Gross’s writes about 10 places where anyone can learn to code and Megan O’Neil’s article A Start-Up Aims to Teach Anyone to Write Computer Code features one of these places (Codecademy). Kevin Lindquist writes that software development isn’t just for coders anymore. Katie Elizabeth lists the reasons why everyone should learn to code while Ch Continue reading

Posted in Database, Eclipse, General Development, GlassFish, Gradle, Groovy, IntelliJ IDEA, Java EE 7, JavaScript, JSON, NetBeans, PHP, Scala, Syndicated | Comments Off on Significant Software Development Developments of 2013

Simple Gradle Java Plugin Customization

As I demonstrated in the post A First Look at Building Java with Gradle, Gradle is particularly concise and easy to apply to the basics of building a Java application when one uses the Java plugin and places files and directories where this plugin expe… Continue reading

Posted in Gradle, Syndicated | Comments Off on Simple Gradle Java Plugin Customization

Book Review: Gradle: Beyond the Basics

Gradle: Beyond the Basics is the “sequel” to Building and Testing with Gradle. According to the Gradle Books page, a third book in this series will be a “set of recipes that uses as the demonstrative tool for enterprise build automation.” I have not r… Continue reading

Posted in Book Review, Gradle, Syndicated | Comments Off on Book Review: Gradle: Beyond the Basics

Gradle Command-Line Conveniences

In my post A First Look at Building Java with Gradle, I briefly mentioned using Gradle’s “gradle tasks” command to see the available tasks for a particular Gradle build. In this post, I expand on that brief mention a bit more and look at some related G… Continue reading

Posted in Gradle, Syndicated | Comments Off on Gradle Command-Line Conveniences