This is a Java library and API for invoking J2735 (2024) encode/decode functions on C code generated by asn1c using the new Foreign Function and Memory API available in Java 22, and a Java wrapper generated by the Jextract tool.
It includes the same complete implementation of J2735 (2024) as the USDOT asn1_codec C++ project, now easily accessible from Java on both Linux and Windows.
It enables converting between these ASN.1 encodings:
- XER - XML Encoding Rules
- UPER - Unaligned Packed Encoding Rules
The j2735-2024-ffm-lib project is a Java library that exposes the MessageFrameCodec class which has two methods:
Converts an XER encoded MessageFrame to UPER
- Parameter xer The XER encoded MessageFrame
- returns Byte array with the UPER encoding
Convert an UPER encoded MessageFrame to XER
- Parameter uper - The UPER encoded MessageFrame
- Returns the XER encoded result
// Initialize the library
MessageFrameCodec codec;
String libResource = System.getProperty("os.name").toLowerCase().contains("win")
? "C:/Users/spongebob/app/asnapplication.dll" // Use windows library
: "/home/app/libasnapplication.so"; // Use Linux library
Path libPath = Paths.get(libResource);
MessageFrameCodec codec = new MessageFrameCodec(262144L, 8192L, libPath);
// Convert XER to UPER
byte[] uper = codec.xerToUper("<MessageFrame><messageId>19</messageId><value><SPAT><intersections><IntersectionState><id><id>12111</id></id><revision>0</revision><status>0000000000000000</status><timeStamp>35176</timeStamp><states><MovementState><signalGroup>2</signalGroup><state-time-speed><MovementEvent><eventState><protected-Movement-Allowed/></eventState><timing><minEndTime>22120</minEndTime><maxEndTime>22121</maxEndTime></timing></MovementEvent></state-time-speed></MovementState><MovementState><signalGroup>4</signalGroup><state-time-speed><MovementEvent><eventState><stop-And-Remain/></eventState><timing><minEndTime>22181</minEndTime><maxEndTime>22181</maxEndTime></timing></MovementEvent></state-time-speed></MovementState><MovementState><signalGroup>6</signalGroup><state-time-speed><MovementEvent><eventState><protected-Movement-Allowed/></eventState><timing><minEndTime>22120</minEndTime><maxEndTime>22121</maxEndTime></timing></MovementEvent></state-time-speed></MovementState><MovementState><signalGroup>8</signalGroup><state-time-speed><MovementEvent><eventState><stop-And-Remain/></eventState><timing><minEndTime>21852</minEndTime><maxEndTime>21852</maxEndTime></timing></MovementEvent></state-time-speed></MovementState><MovementState><signalGroup>1</signalGroup><state-time-speed><MovementEvent><eventState><stop-And-Remain/></eventState><timing><minEndTime>21852</minEndTime><maxEndTime>21852</maxEndTime></timing></MovementEvent></state-time-speed></MovementState><MovementState><signalGroup>5</signalGroup><state-time-speed><MovementEvent><eventState><stop-And-Remain/></eventState><timing><minEndTime>21852</minEndTime><maxEndTime>21852</maxEndTime></timing></MovementEvent></state-time-speed></MovementState></states></IntersectionState></intersections></SPAT></value></MessageFrame>");
// Convert UPER to XER
String xer = codec.uperToXer(HexFormat.of().parseHex("001338000817a780000089680500204642b342b34802021a15a955a940181190acd0acd20100868555c555c00104342aae2aae002821a155715570"));A native, dynamic library, libasnapplication.so, is generated from asn1c generated C code. The library is installed on the same image as the Java API.
The Java library, j2735-2024-ffm-lib, includes code generated by the Jextract tool.
Native method calls and native data structures are handled inside a Java thread-scoped "Arena".
Arenas are FFM's way of limiting the scope and lifetime of memory used by native methods, to prevent memory leaks and security issues.
See: docs.oracle.com: Memory Segments and Arenas
Java FFM bindings are generated by running the Jextract tool on the src/convert.h header file.
Prerequisites:
- The Java library Java 22+ is required to use the library.
- The build scripts require Docker.
- Visual Studio 2022 is required to rebuild for Windows.
To get started check out the repository with submodules
git clone --recurse-submodules https://github.com/neaeraconsulting/j2735-ffm-java.gitThe native library for Linux and the jextract bindings can be regenerated by running:
docker compose -f docker-compose-build.yml up --build -dwhich pulls in the generated C files from asn1_codec, compiles them with the C API in the src folder.
The unzipped C files are copied to the generated-files folder. They are not persisted to the repo since they are identical to the files from asn1_codec, but it can be useful to have the unzipped files for debugging the src/convert.h API in an IDE.
The compiled shared library for Linux is copied to the lib folder.
The Java source code from jextract is copied to the generated-jextract folder.
The Windows library doesn't have an automated build process. It can be recreated using Visual Studio 2022 (not VSCode) with the Clang compiler for Windows. Some edits to the generated C files are required to build for Windows. Follow the instructions here: C codec edits for Windows. And then build via CMake in Visual Studio. The CMakeSettings.json file contains the Visual Studio configuration to use CMake with the clang compiler.
After regenerating the native libraries to the lib folder, also be sure to copy them to the j2735-2024-ffm-lib/src/test/resources/j2735ffm folder since they are required for the unit tests in that Java project via:
cd lib
cp libasnapplication.so ../j2735-2024-ffm-lib/src/test/resources/j2735ffm/
cp asnapplication.dll ../j2735-2024-ffm-lib/src/test/resources/j2735ffm/The unit tests can be run in either Linux or Windows.
To test the library:
cd j2735-2024-ffm-lib
./gradlew clean build testRequires:
- Docker
Run docker-compose from the root directory:
docker compose -f docker-compose-api.yml up --build -dUse the *.http scripts in the /j2735-2024-api/http-tests directory to test the API. These scripts work with
IntelliJ IDE, or in VSCode with the REST Client extension.
The following translation methods are available at base URL https://localhost:4000 All methods are POSTs.
| Method | Description |
|---|---|
| /uper/bin/xer | UPER binary to XER |
| /uper/hex/xer | UPER hex string to XER |
| /xer/uper/bin | XER to UPER binary |
| /xer/uper/hex | XER to UPER hex string |
Content types are:
| Encoding | Content Type |
|---|---|
| UPER binary | application/octet-stream |
| UPER hex | text/plain |
| XER | application/xml |
Swagger UI documentation for the Demo REST API is available at:
http://localhost:4000/swagger-ui.html
The OpenAPI specification is available in JSON format at:
http://localhost:4000/api-docs
or in YAML format at: