Eight Tools Every Java Developer Should Know (and Love)
The Stormpath team uses eight tools for daily tasks on their Java SDK team. Here's the full list with detailed descriptions of each.
Join the DZone community and get the full member experience.
Join For FreeAt Stormpath, we take quality and productivity very seriously. As any good craftsmen already knows, having talent is not enough, you also need the right tools for the job. Engineering isn’t just a science, it’s also an art, so although we undoubtedly have talent (wink wink) at Stormpath, we always look to supplement with the tool that best fits our needs. Our engineers are always eager to share new tools with the rest of the team. And now, with all the other talented Java developers out there!
In this post, I’ll share the tools that our Java SDK team uses for daily tasks, how we use them, and hopefully, share a few tips that will be useful for you.
1. Groovy
Rather than writing our tests in Java, we do so with Groovy. Why? Well, it provides all these capabilities for free:
Relaxed Java-like syntax: It is Java syntax, but with fewer rules. For example semicolons, variable types, and access modifiers are all optional. The latter has a huge benefit for testing. Since access modifiers are not strict, your test can read and assert internal state for the class being tested. For example, let’s assume you have this class:
public class Foo {
private String bar = null;
public void setBar(String bar) {
this.bar = bar;
}
}
If you want to test that the setBar(String)
method works ok (meaning that it properly changes the value of the private property called bar
) you can simply do so by reading the value of that variable with Groovy. Java would not allow something like that (at least not without resorting to reflection).
@Test
public void test() {
def foo = new Foo()
foo.setBar("hello")
Assert.isTrue(foo.bar.equals("hello"))
//groovy allows us to access the private property called bar
}
Power Assertions: Groovy provides a powerful variant of assert
also known as power assertion statement
. Groovy’s power assert clearly shows evaluation results when the validation fails. Additionally, it is more readable than its Java counterpart.
Assert.isTrue(foo.bar.equals("hello"))
This can be translated to:
assert foo.bar == "hello"
When the assertion fails it will show a very clear description of what has happened:
assert foo.bar == "goodbye"
| | |
| | false
| hello
Foo@12f41634
Mocking: When using Java, dynamic mocking frameworks (like EasyMock, PowerMock and Mockito are very popular. All those frameworks can be used easily with Groovy. Yay!
2. Rest-Assured
Our backend provides a REST API service for creating and managing user accounts. Our Java SDK is one of many different SDKs providing a language-specific client-side model to simplify interactions. Some of these SDKs also provide a web layer to interact with the backend without needing to write any code.
In order to guarantee interoperability among all these web frameworks, they must behave exactly the same. Therefore we had to create a set of HTTP-based integration tests that every framework is validated against. That’s our Test Compatibility Kit. This project is maintained by all our SDK engineers, and not all of them master the same programming languages. Therefore we had to utilize a language-agnostic testing tool. That’s when Rest-assured came to the rescue.
Rest-assured is a simple Java DSL (domain-specific language) for testing REST services. Not only it is very simple to use and get started with, even for developers that have never used Java before, it is also incredibly powerful. It provides advanced features like detailed configuration, filters, custom parsers object, CSRF, and OAuth 2.0. It was built from the ground up to provide an extremely simple syntax: given-when-then.
For example: let’s see how easy it is to validate that "a post to /login with valid credentials must return status code 302
":
given()
.accept(ContentType.HTML)
.formParam("login", account.username)
.formParam("password", account.password)
.when()
.post(LoginRoute)
.then()
.statusCode(302)
You can see a lot of different Rest-assured tests in our TCK repo.
3. Cargo Plugin
In order to have our Java SDK validated by the TCK we need to start one of our Web Examples so those tests can be executed against it. Logically, we wanted that validation to happen automatically on every build. Cargo Plugin is used exactly for that purpose.
Cargo is a thin wrapper to manipulate various types of application containers in a standard way. With Cargo, we were able to run our examples in different Servlet Containers (like Jetty and Tomcat) quite effortlessly. We simply configured the Cargo Maven2 Plugin in our pom files to start a Servlet Container (Tomcat 7) and deploy the recently built War file during the Integration Testing phase. You can see the working configuration in our Servlet Plugin Example.
4. Git
What can we say about Git that you don’t know already? For an in-depth look at the benefits of Git, you can simply read their About page.
Our Java SDK Team is spread around the globe and almost never sitting next to each other. Git safeguards every piece of code that we write. Here are some cool commands that have saved us lot of time and headaches:
git mv --force foo.java Foo.java
: In case-insensitive file systems changing the case of file names will be troublesome. This command makes git aware that the filefoo.java
has been renamed toFoo.java
.git diff-tree --no-commit-id --name-only -r <commit_ID>
: see all the files that where changed in the commit<commit_ID>
git diff --name-only SHA1 SHA2
: List all the files that have changed between commit SHA1 and SHA2- Search for a String throughout all the history of a file:
Create a file called search.sh
and paste this:
git rev-list --all $2 | (
while read revision; do
git grep -F $1 $revision $2
done
)
The command can then be executed like this: sh ./search.sh string_to_search file_where_to_search
5. GitHub
GitHub not only provides free hosting for our Git project, it has also the invaluable benefit of opening the source code up for the world to see it. This encourages people to try it, communicate with us, and participate, which ultimately improves the quality of everyone’s projects and grow all our technical knowledge.
GitHub also allows us to keep track of our issues. Customers can then submit feature requests and report bugs. They can also get notifications about progress that we make.
6. Maven
Maven is already famous enough, so I won’t bore you with a long explanation of why we are using Maven to take care of our build process. However, I can share a few useful tips to get even more out of Maven:
Consolidate Dependencies: In a multi-module project you should define every single dependency right in the root pom.xml
inside the <dependencyManagement>
tag. Once you do that, all the sub-modules can depend on those dependencies without having to specify their versions. This way of managing your dependencies (e.g, updating versions) can be done in a centralized place, and all the sub-modules will pick up changes automatically. For example, root pom.xml
:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jjwt.version}</version>
</dependency>
...
<dependencies>
<dependencyManagement>
Sub-module’s pom.xml
:
<dependencies>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId> <!-- note that no version has been specified -->
</dependency>
...
<dependencies>
Prevent sub-module deployment: During release-time we want all our sub-modules to be released, but how can we avoid a sub-module (like an example) being released?. Simple, just add the following in the pom file to the module that you do not want to release:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.7</version>
<configuration>
<skip>true</skip> <!-- this this the important line -->
</configuration>
</plugin>
Skip Integration Tests: We have many integration tests that take quite a long time to complete. These tests validate that the interaction with the backend is working properly. During regular local development, we modify code several times before the new feature or bug-fix is complete. There is not need for those intermediate local builds to be validated against the backend each time, this would significantly slow the development process. Therefore, we have configured our Java SDK to automatically run ITs only when the build is running in our CI server. You can do the same like this:
In your root pom.xml
file:
<properties>
<skipITs>true</skipITs>
</properties>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<skipITs>${skipITs}</skipITs>
<includes>
<include>**/*IT.*</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<build>
As you can imagine, all the integration test files must suffixed with the letters IT
for this configuration to work. For example, ApplicationIT.groovy
or I18nIT.groovy
.
Then, when we do want to have the ITs running, we execute the build like this: mvn clean install -DskipITs=false
.
7. JWT Inspector
In our Java SDK we use JWTs quite heavily to transport data in a secure and trouble-free way. When testing and troubleshooting we need to analyze the content of the JWTs that we receive in the browser. Those tokens can be either in the URL, in a cookie, or in local storage. JWT Inspector is a browser extension we built to help us decode and inspect JSON Web Tokens directly from the console or in the built-in UI. You do not need to trace those tokens in your app. You simply press the extension button and JWT Inspector will automatically show all the information you need. You can then copy whatever claim of the expanded token you need.
8. Postman
We work quite heavily with REST API requests. Writing REST requests is not always user-friendly; the actual syntax depends on the tool that we are using, like curl or HTTPie. Both are quite readable but sometimes it is difficult to remember the exact syntax. Additionally, when troubleshooting, we need to test some requests and their outcome. When they fail we are not sure whether the problem is in the request or in the endpoint itself. We end up losing time simply because we doubt the correctness of the request we are writing.
Postman makes writing REST API requests simple. It also provides many valuable features like saving and re-using requests, generating code (java, python, curl, etc.), and grouping requests to run them sequentially. Postman helps you build complex commmands thanks to its user-friendly UI. All you have to do is complete a form. Can it get better than that?
Final Thoughts
Using the right tools not only allows you to save time and reduce effort, it also improves the overall quality of your product and makes your daily work more enjoyable. We should be always open to discovering and learning new tools. It might require some effort at first but you will soon realize that it was absolutely worth the time you invested.
I’d love to hear about the developer tools that have been your personal lifesavers. Share them in the comments below, or tweet us @gostormpath!
Published at DZone with permission of Mario Antollini, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments