Unit API + Spring Boot (1)

Published: Feb 26, 2021 by Simon Schneider

TLDR; If you work with SI-Units/Quantities in your application, try out the Unit API which is an implementation of JSR-385 with focus on the SI System redefinition, modularity and support for Java SE 8. It integrates well into various Frameworks, Libraries and Languages, such as Spring Boot, Hibernate, Jackson, Kotlin and more.

Introduction

In the late 90s NASA send a sattelite to Mars, which should study the martian climate, atmosphere and surface changes and also act as a communications relay. After a successful 10 months of travel to Mars, on Sepmtember 23 1999 communications with the spacecraft was lost and never restored. During orbital insertion the Mars Climate Orbiter burned and broke into pieces. After extensive investigations a NASA review board found that the problem was in the software controlling the orbiter’s thrusters. The software calculated the force that the thrusters needed to exert in pounds of force. A second piece of code that read this data assumed it was in the metric unit—”newtons per square meter”. The interface was specified to read/write the data in “newtons per square meter”, but this interfaces was not tested properly as NASA confirmed. The building costs of the 338-kilogram robotic space were $125 million.

This Story shows the problem of conversion between different units and there specification in interfaces. Usually an interface allows to only send the value of a quantity and not the unit it was specified with. Therefore this mistakes happend and will be happening if interfaces are designed in this way. We have also seen, that this kind of errors can have fatal consequences, in this instance $125 million. A possible solution is to use more complex data types which allow the specification of a unit in the interface.

JSR-385

In the JSR-385 specification it says:

JSR 385 proposes to establish safe and useful methods for modeling physical quantities. The specification includes:

  • Interfaces and abstract classes with methods supporting unit operations, including:
    • Checking of unit compatibility
    • Expression of measurement in various units
    • Arithmetic operations on units
  • Concrete classes implementing standard unit types (such as base and derived) and unit conversions.
  • Concrete classes for parsing and formatting textual unit representations.
  • A “database” or equivalent repository/system of predefined units.

For example, this framework could be used in a project in which it may be unclear whether a person’s mass is expressed in pounds, kilograms, or stones. Therefore its a good idea to use a standard solution which is both safer and more efficient, saving developers valuable time for domain-specific work.

Definitions

The JSR-385 expresses the values and their assigned units as objects of the type Quantity. A Quantity has to be typed with java generics, e.g. Quantity<ElectricCurrent>. A Unit can be specified for a specific Quantity type and contains all informations how to convert a given quantity value.

Implementation

There are currently multiple implementations for the JSR-385.

  • Indriya which is the original reference implemantion for the JSR-385
  • unit-api on which we will take a closer look in the next chapter

Unit API as JSR-385 implementation

The Indriya implemenation for the JSR-385 is a black box framework, which is not designed to be expanded in many ways. It is possible to add additional units, but there is no generic way of how to create additional units and work with them in annotations. Therefore the unit-api was started in 2020 and adapted the Indriya implemenation. The new unit-api allows to use Units in annotations and integrates the JSR-385 into multiple other frameworks. It should be possible to use the JSR-385 in Spring Boot without configuration.

Unit API with Jackson

The first example shows how to create a rest api which allows to get the current weather data in SI-Units. The Source of the current weather data is the WeatherService. This Service will provide static result, which makes it easier to created tests.

Then a controller has to be created, which exposes an endpoint to query the current weather data:

The controller uses the WeatherResponse class, which contains two attributes. The first attribute represents the current temperature, the second attribute the current humidity.

This application is able to provide the current weather data, which we can retrieve with following command.

curl http://localhost:8080/api/v1/weather
{
    "temperature":"30 ℃",
    "humidity":"45 %"
}

Dynamic Units

Usually it is enough to provide an endpoint with static units. But the described approach can be expanded to support dynamic units.

The controller has to have a parameter which allows the switch between different units.

As you can see we also have two new data transfer object classes.

The new endpoint should return degree Celsius by default.

curl http://localhost:8080/api/v2/weather
{
    "temperature":"30 ℃",
    "humidity":"45 %"
}

And it should return the temperature in Kelvin if requested.

curl http://localhost:8080/api/v2/weather?unit=K
{
    "temperature":"303.15 K",
    "humidity":"45 %"
}

Conclusion

As we have seen above the unit-api makes it simple to use the JSR-385 with Spring Boot. We can also use the unit-api on the persitence layer, but this will be discussed in the next blog post, of this series. All Code can be found on Github. But one question is still not answered: How would a Ground Station be designed with JSR-385?

Mars Climate Orbiter Groundstation - Spring Boot

The question “How would a Ground Station be designed with JSR-385?” should be answered in seperate blog post. But for now you could checkout this challenge which tries to answer the question.

Simon Schneider

Simon Schneider

Senior Software Engineer

Passionate software engineer with a focus on the development of high-availability systems, full-text search and data analysis with Elasticsearch.

Theme built by C.S. Rhymes