Category Archives: Java

API-first meets Java

Introduction

In this workshop, we’re going to define a REST API and implement it in Java. Furthermore, we’re going to do it using the API-first methodology, which means we’re going to first define the API in a language-independent fashion (using OpenAPI) and then we’re going to implement that API in Java.

Why would we do this? In the API-first methodology, the API exists independently from its implementation. There are a number of good reasons for doing this, the most important one being that the API represents a contract with its clients, which must maintain its integrity over time and therefore must be free of implementation details. In order to avoid getting stuck on a specific technology stack, it must be possible to take an existing API and reimplement it on a different technology stack (e.g. Go, Python, Javascript) without breaking the API contract the clients depend on. Additional benefits include being able to take advantage of documentation and test tools which are available to APIs defined using standards like OpenAPI.

Why use Java? After all, there are a number of other languages which are better suited to implementing REST APIs. The answer is that Java is still the most important language for enterprise development and therefore there are many situations where it makes sense to implement REST services in Java. Luckily, tools like Spring Boot and the OpenAPI/Swagger Java Inflector make it relatively straightforward to use the API-first methodology in Java.

Whats wrong with the “API-second” approach: The traditional approach (let’s call it the API-second approach) is to publish an existing Java service using Jersey or some other REST framework. However, this approach turns out to be a bad idea in practice since it’s almost impossible to avoid Java-specific details leaking into the API and later changes to the implementation may inadvertently break the API.

The technology stack used in this workshop

  • Java
  • Spring Boot (Java application server)
  • Swagger Inflector (to wire the API to Java)
  • Visual Studio Code (Editor/IDE)
  • RestAssured.io (to test the api)

The code for the workshop is available on GitHub at:

https://github.com/armstrongconsulting/code-samples/tree/master/spring-boot-api-first-demo

Step 1: Design a first version of your API.

The online swagger editor is a great tool for defining the API. Point your browser at https://editor.swagger.io, Choose the “File/Import Url” and enter “https://petstore.swagger.io/v2/swagger.json”, since for the purposes of this workshop, we’ll implement the well-known “petstore” API. With the online editor you can very quickly create your own first draft of your API. When you are satisfied, download a YAML version of your API and store it for later use and update.

Step 2: Boot up your framework with Spring Initilizr in Visual Studio Code

Create a new spring-boot project, as described here: https://code.visualstudio.com/docs/java/java-spring-boot. Use the latest spring boot version (we used 2.1.1 when creating this workshop) and add the “Web” and “Jersey (JAX-RS)” dependencies (since swagger inflector is based on jersey).

Add the swagger inflector dependency to the pom.xml.


Note: The 1.xx branch of swagger-inflector is only compatible to Open-Api Version 2, the 2.xx branch is currently under development and will support OAS3 as well.

Step 3: Run an implementation of your API with swagger-inflector, explore it with swagger-ui

In order that swagger inflector can interpret your API, follow these steps:

Copy the downloaded yaml file to src/main/ressources/swagger.yaml

Configure  jersey to load the swagger inflector resource. We have combined all relevant code in one configuration class, which you’ll  find here (SwaggerConfig.java). The “SwaggerConfig.java” additionally configures CORS so that your API can be contacted from anywhere.

Configure some important application.properties wich

  • Boot up the server at port 8080
  • Configure some important Jackson properties so that dates are properly serialised
  • set the jersey application path to /api

Allow your application to serve static content (e.g. the swagger-ui application) by creating a WebConfig.java

The artefacts for swagger-ui are brought in via webjars simply by adding the following to the pom.xml

If you run your application now, swagger ui should boot up under the following url

http://localhost:8080/webjars/swagger-ui/3.20.3/index.html?url=/api/v2/swagger.yaml

(Note: this assumes that the “basePath” in swagger.yaml is set to /v2!)

Step 4: Implement your api

The model

Swagger generator is a great tool to save us from a lot of boilerplate.  Together with maven it will help you build your model. Adding the the swagger-codegen-maven-plugin and the build-helper-maven-plugin to the pom.xml does the magic. For details see the pom.xml on GitHub

The controller

Other swagger frameworks depend on generating the api specification from the implementation, or to generate the implementation from the api specification. Swagger inflector takes an alternative approach and interprets the swagger.yaml file on the fly and routes the request to a controller.

Here is our example of implementing one api method:

The sample implementation simply takes the provided Id, adds a dummy name and returns the “demo pet”. Since swagger inflector is running in “DEVELOPMENT” mode (see SwaggerConfig.java), it automatically provides dummy implementations for all other methods.

Step 5: Test your API

We have chosen rest-assured to test our APIs in unit and integration tests, since it’s simple and intuitive (see pom.xml which shows which artefact will be required in the test scope). The following unit test verifies that our PetController returns a valid result when fetching a pet:

Conclusion

Its perhaps not the easiest way to publish a REST API, but combining Java and the API-first methodology provides the best of both worlds – the correctness of an API defined using the OpenAPI standards and the performance, static typing and enterprise development ecosystem of Java.

Abbreviated component paths in wicket tester

Wicket tester combined with Mockito is fantastic for unit testing your web application. However, developing the tests is harder than it should be because you have to refer to components by their path rather than their id.

For example, to clock the OK button on a page, I need something like:

tester.executeAjaxEvent(“border:form:pagetitlecontainer:ok”. “onclick”);

i.e. instead of “ok”, I must refer to the button by its full path “border:form:pagetitlecontainer:ok”. This seems tedious – if I know that I only have one component on the page with the id “ok”, why can’t I just use “ok”. Wicket tester should notice that the component is not available and traverse the component hierarchy for it. If its ambiguous then it can complain, but if not, then it should be OK.

To get around this limitation, we override the getComponentFromLastRenderedPage method of the WicketTester class as follows:

[sourcecode language=”java”]
@Override
public Component getComponentFromLastRenderedPage(final String path) {
// first check if we can find the component with the specified path – if not, check if its an abbreviated path
String fullPath = lookupPath(getLastRenderedPage(), path);
if (fullPath == null)
return null;

return super.getComponentFromLastRenderedPage(fullPath);
}

public String lookupPath(final MarkupContainer markupContainer, final String path) {
// try to look it up directly
if (markupContainer.get(path) != null)
return path;

// if that fails, traverse the component hierarchy looking for it
final List candidates = new ArrayList();
markupContainer.visitChildren(new IVisitor() {
private static final long serialVersionUID = 1L;

Set visited = new HashSet();

@Override
public Object component(Component c) {
if (!visited.contains(c)) {
visited.add(c);

if (c.getId().equals(path))
candidates.add(c);
}
return IVisitor.CONTINUE_TRAVERSAL;
}
});
// if its unambiguous, then return the full path
if (candidates.isEmpty()) {
fail(“path: ‘” + path + “‘ not found for ” +
Classes.simpleName(markupContainer.getClass()));
return null;
} else if (candidates.size() == 1) {
String pathToContainer = markupContainer.getPath();
String pathToComponent = candidates.get(0).getPath();
return pathToComponent.replaceFirst(pathToContainer + “:”, “”);
} else {
String message = “path: ‘” + path + “‘ is ambiguous for ” + Classes.simpleName(markupContainer.getClass()) + “. Possible candidates are: “;
for (Component c : candidates) {
message += “[” + c.getPath() + “]”;
}
fail(message);
return null;
}
}
[/sourcecode]

Wicket needs a component catalog

I’m a big fan of Apache Wicket, but there’s an urgent need for a better-organized component-ecosystem around Wicket. To write a real web application you need a framework (that’s Wicket) and visual components (that’s JQuery, YUI, Recaptcha etc) and you need the two to work together smoothly.

A newcomer to Wicket should be impressed by the clean, component-oriented approach to producing the GUI for his application, but a production web application needs more than just HTML. So, inevitably, the next step is to try to find the stuff which will make your web-application look like all those other web 2.0 sites out there. However, very few of the Wicket components referenced from the Wicket home pages are “best-of-breed” and a certain amount of disappointment soon sets in.

Take the wicket example captcha implementation for example. There are two problems here: (a) the implementation produces a captcha image which is not only difficult for robots to read, but also pretty impossible for humans and (b) everybody else is already using recaptcha so why even bother distracting developers with yet-another home-spun implementation.

The Wicket community might react by saying “well, there are enough blogs describing how to use recaptcha with Wicket, so where’s the problem?”. Well the problem is that these blogs typically provide their description in a way which reflects their own expertise rather than that of the reader, which means that a novice Wicket programmer may or may not be able to follow the instructions to successfully integrate recaptcha into his application.

Or to put it another way, developers blogs are not a substitute for organized, tested and documented component libraries.

What could help, on the other hand, is a catalog of components, with ratings and a compatibility matrix indicating tested interoperability with other components/browsers etc.

By the way what prompted me to write this post was that yesterday I finally used a few of the Visural Wicket components (based on JQuery) and they are fantastic – well thought out APIs, styling etc. What I don’t understand is that mediocre-to-lousy versions of equivalent components (such as the Wicket extensions modal window or the wicketstuff lightbox) feature much more prominently on the Wicket sites, so the novice programmer is far more likely to use them (and be bitterly disappointed) than to use Visural Wicket (and be delighted).

Wicket adoption would likely be accelerated if the end-to-end experience of producing the first production web application involved a bit less trial-and-error and a bit more delight.

Shadowed variables in inner classes

Yesterday we had a bug caused by the following situation: a class X had a variable “user”. Class X had an inner, anonymous class extending class Y. Inside the inner class a reference was made to the “user” variable from the enclosing class X. Somebody then added a protected variable “user” to class Y. The java compiler silently updated the reference to “user” within the inner class from X.user to Y.user.

This is pretty nasty and I hoped that some of the code-checking tools would warn about about it, so I checked the code with PMD, Findbugs and Checkstyle. Unfortunately, none of them flagged the issue.

Deciphering anonymous class references like MyPage$1$1$2

If you work with anonymous classes a lot (as Wicket applications do), you sometimes get confronted with compiler/tool messages referring to anonymous (inner) classes with names like MyPage$1$1$2 (for instance in FindBugs reports). Its pretty tedious to figure out which class is meant. Maybe there’s a better way, but what I do is go to the target directory and call “javap MyPage$1$1$2.class”. This produces a decompiled version of the class which makes it pretty clear which class it is.

Wicket 1.4 and browser tabs

We had an amazingly annoying problem in a Wicket application. A specific user was continuously having problems with ajax controls on pages (search fields, auto-complete fields etc). The problems were caused by PageExpiredExceptions. We couldn’t understand why only this one user had these problems. This went on for ages, until today I found out that Wicket 1.4 sets a default limit of 5 page maps per session. This specific user typically worked with multiple browser tabs on the application and once he went over 5, some of the page maps got evicted and the ajax stuff started failing.

The solution was to call “getSessionSettings().setMaxPageMaps(100)” to allow up to 100 page maps per session.

Adding AnnotatedConstraintBehavior to TextAreas

A while back I blogged about using an annotated constraint behavior to limit input in Wicket TextFields based on domain model annotations (http://blog.armstrongconsulting.com/?p=22). So if we annotate our domain models as follows:

[sourcecode language=”java”]
@Length(max = 40)
private String firstName;
[/sourcecode]

that gets automatically be translated into a maxlength=40 attribute on any text field bound to firstName (we use a form visitor on a custom form class to add the behavior to all text fields in the form).

That’s pretty cool, but unfortunately, it only works for text inputs because textarea doesn’t support the maxlength attribute. This really bothered me because its really important to limit the length of textareas since that’s where people try to paste in huge blocks of text and its annoying to only find out the limitation after submitting the form.

So today, I updated the behavior to also handle textareas. There’s a javascript workaround which simulates the maxlength behavior on textareas. I took the javascript from http://cf-bill.blogspot.com/2005/05/unobtrusive-javascript-textarea.html and in the renderHead of the behavior, I add the javascript.

Here’s the code – its in three files: AnnotatedConstraintBehavior.java (the behavior implementation), AnnotatedConstraintBehavior.js (the javascript needed to simulate maxlength on textareas) and ACForm.java (a form which does two extra things: (a) it validates its properties based on annotated constraints (like @NotNull and @Length)) and (b) it adds maxlength to text fields and textareas using the AnnotatedConstraintBehavior).

[sourcecode language=”java”]
// AnnotatedConstraintBehavior.java
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import javax.validation.constraints.NotNull;

import org.apache.commons.validator.EmailValidator;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.ResourceReference;
import org.apache.wicket.application.IComponentOnBeforeRenderListener;
import org.apache.wicket.behavior.AbstractBehavior;
import org.apache.wicket.markup.html.IHeaderResponse;
import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.model.AbstractPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.IPropertyReflectionAwareModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.util.lang.PropertyResolver;
import org.apache.wicket.validation.IValidatable;
import org.apache.wicket.validation.validator.StringValidator;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;

/**
* Configure a Wicket Component based on Hibernate annotations (@NotNull and @Length(min=x,max=y)).
*

* Inspects the Model of a FormComponent and configures the Component according to the declared Hibernate Annotations used on the model object.
* NOTE: This means the Component‘s Model must be known when {@link #configure(Component) configuring} a Component.
*

*
*

* This object can be used as a Behavior to configure a single Component.
* NOTE: this object is stateless, and the same instance can be reused to configure multiple Components.
*

*
*

*
*

* This object can also be used as a component listener that will automatically configure all FormComponents based on Hibernate annotations. This ensures that an entire application respects annotations without adding custom
* Validators or Behaviors to each FormComponent.
*

*
*

*
* @see http://jroller.com/page/wireframe/?anchor= hibernateannotationcomponentconfigurator
* @see http ://jroller.com/page/wireframe/?anchor=hibernate_annotations_and_wicket
*/
@SuppressWarnings(“serial”)
public class AnnotatedConstraintBehavior extends AbstractBehavior implements IComponentOnBeforeRenderListener {
static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(AnnotatedConstraintBehavior.class);

@SuppressWarnings(“unchecked”)
private static Map configs = new HashMap() {
{
put(NotNull.class, new AnnotationConfig() {
public void onAnnotatedComponent(Annotation annotation, FormComponent component) {
component.setRequired(true);
}
});
put(Length.class, new AnnotationConfig() {
public void onAnnotatedComponent(Annotation annotation, FormComponent component) {
int max = ((Length) annotation).max();
log.debug(“adding maxlength=” + max + ” attribute to ” + component.getMarkupId());
component.add(new AttributeModifier(“maxlength”, true, new Model(Integer.toString(max))));
component.add(StringValidator.maximumLength(max));
}
});

put(Email.class, new AnnotationConfig() {
public void onAnnotatedComponent(Annotation annotation, FormComponent component) {
component.add(new StringValidator() {
@Override
protected void onValidate(IValidatable validatable) {
if (!EmailValidator.getInstance().isValid(validatable.getValue())) {
error(validatable);
}

}
});
}
});

}
};

@Override
public void renderHead(IHeaderResponse iHeaderResponse) {
super.renderHead(iHeaderResponse);
iHeaderResponse.renderJavascriptReference(new ResourceReference(AnnotatedConstraintBehavior.class, “AnnotatedConstraintBehavior.js”));
}

@Override
public final void bind(Component component) {
super.bind(component);
configure(component);
}

@Override
public final void onBeforeRender(Component component) {
if (!component.hasBeenRendered()) {
configure(component);
}
}

void configure(Component component) {
if (!isApplicableFor(component)) {
return;
}
FormComponent formComponent = (FormComponent) component;
for (Annotation annotation : getAnnotations(component.getDefaultModel())) {
Class annotationType = annotation.annotationType();
AnnotationConfig config = (AnnotationConfig) configs.get(annotationType);
if (null != config) {
config.onAnnotatedComponent(annotation, formComponent);
}
}
}

private Collection getAnnotations(IModel model) {

try {
// Only if a setter method is available we’ll search for the
// related field and find its Annotations.
Method setter = ((IPropertyReflectionAwareModel) model).getPropertySetter();

String name = setter.getName();

if (name.startsWith(“set”) && name.length() > 3) {
name = name.substring(3, 4).toLowerCase() + name.substring(4);
} else {
return Collections.emptyList();
}

Object target = ((AbstractPropertyModel) model).getTarget();
Field field = PropertyResolver.getPropertyField(name, target);
if (field == null) {
return Collections.emptyList();
}

return Arrays.asList(field.getAnnotations());
} catch (Exception ignore) {
return Collections.emptyList();
}
}

private boolean isApplicableFor(Component component) {
if (!(component instanceof FormComponent)) {
return false;
}
IModel model = component.getDefaultModel();
if (model == null || !IPropertyReflectionAwareModel.class.isAssignableFrom(model.getClass())) {
return false;
}

return true;
}

/**
* simple interface to abstract performing work for a specific annotation.
*/
private static interface AnnotationConfig extends Serializable {
void onAnnotatedComponent(Annotation annotation, FormComponent component);
}
}
[/sourcecode]

[sourcecode language=”javascript”]
// AnnotatedConstraintBehavior.js
// javascript to simulate maxlength behavior on textareas
// source: http://cf-bill.blogspot.com/2005/05/unobtrusive-javascript-textarea.html


[/sourcecode]

[sourcecode language=”java”]
// ACForm.java
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import org.apache.wicket.Component;
import org.apache.wicket.Component.IVisitor;
import org.apache.wicket.behavior.AbstractBehavior;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.IModel;
import org.wicketstuff.jsr303.PropertyValidation;

public class ACForm extends Form {
private static final long serialVersionUID = 1L;

static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Placeholder.class);

public ACForm(String id, IModel model) {
super(id, model);
add(new PropertyValidation());
}

public ACForm(String id) {
super(id);
}

@Override
protected void onBeforeRender() {
super.onBeforeRender();
visitChildren(TextField.class, new AddBehaviorVisitor(new AnnotatedConstraintBehavior()));

// note: textarea doesn’t actually support the maxlength attribute, but we add it anyway and enforce it with javascript (the AnnotatedConstraintBehavior adds it)
visitChildren(TextArea.class, new AddBehaviorVisitor(new AnnotatedConstraintBehavior()));
}
}

class AddBehaviorVisitor implements IVisitor, Serializable {
private static final long serialVersionUID = 1L;
private final AbstractBehavior behavior;
Set visited = new HashSet();

public AddBehaviorVisitor(AbstractBehavior behavior) {
this.behavior = behavior;
}

@Override
public Object component(Component component) {
if (!visited.contains(component)) {
visited.add(component);
component.add(behavior);
}
return IVisitor.CONTINUE_TRAVERSAL;
}
}

[/sourcecode]

Using Wicket’s CheckBoxMultipleChoice

When I started with Wicket, I remember fighting with CheckBoxMultipleChoice for hours trying to get it to work. I just used it again today and was surprised at how easy it is to use once you’re familiar with how Wicket works. So for anyone struggling with it, here’s how to do it.

Say we want to display a list of Projects associated with a User and we want to do it with the CheckBoxMultipleChoice. The projects which the user currently has access to should be checked initially. Checking or unchecking boxes will add or remove access to projects.

You can accomplish this with the following code:

[sourcecode language=”java”]
add(new CheckBoxMultipleChoice(“projects”, new Model(userProjects), allProjects));
[/sourcecode]

Assuming you have a span with wicket:id=”projects” in your HTML, this will display a checkbox for each project found in the “allProjects” list. Those which are also in the “userProjects” list will be checked. After submitting the form, the “userProjects” list will hold those which were checked when the form was submitted.

Note: I have omitted a renderer – that’s because my Project class has a toString() method which returns its name. That’s allows Wicket to render it correctly without an explicit renderer.

Second thing to note is that “userProjects” must be an ArrayList of Projects, not a List (as your service method would normally return it). The reason for this is that the Model demands a Serializable class so the easiest thing is to define userProjects as follows:

[sourcecode language=”java”]
ArrayList userProjects = new ArrayList(service.getUserProjects());
[/sourcecode]

The choices parameter (allProjects) can be a List, so you can use it straight from your service method.

Hope that helps anyone trying to use CheckBoxMultipleChoice for the first time.

How to display an enum in a dropdown in Wicket

Its often useful to use an enum as the model for a dropdown (or radio group) in Wicket, but not immediately obvious how to handle the display of the values. Lets say I have an enum with three colors:

[sourcecode language=”java”]
enum Color { RED, GREEN, BLUE };
[/sourcecode]

I can hook this up to a dropdown with the following code:

[sourcecode language=”html”]

[/sourcecode]

[sourcecode language=”java”]
enum Color { RED, GREEN, BLUE };
private Color color = Color.GREEN;
add(new DropDownChoice(“color”, Arrays.asList(Color.values()), new EnumChoiceRenderer(this)));
[/sourcecode]

[sourcecode language=”java”]
Color.RED=Red
Color.GREEN=Green
Color.BLUE=Blue
[/sourcecode]

Now I get what I wanted – a dropdown displaying “Red”, “Green” and “Blue”.

Mockito

We just started using Mockito for unit testing of our Wicket applications. Its a great tool, allowing us to easily mock out our service layers on a test-by-test basis.

In the example below, we’re testing a page called ItemPage. It takes an id of an item to load – internally the page uses itemService.find(id) to load the item from the database. Using Mockito, we mock out the itemService.find call to return a test item.

[sourcecode language=”java”]
public class TestItemPage extends WicketTestcase {
private static final long serialVersionUID = 1L;

@Test
public void TestItemPage() {
when(itemService.find(Mockito.anyInt())).thenAnswer(new Answer() {

@Override
public Item answer(InvocationOnMock invocation) throws Throwable {
final int id = (Item) invocation.getArguments()[0];
Item item = new Item(id);
item.setTitle(“test”);
item.setDeadline(new Date());
return item;
}
});

tester.startPage(new ItemPage(12345));
tester.assertRenderedPage(ItemPage.class);
}
}
[/sourcecode]