Typed access to SAP tables from the JVM, over the RFC_READ_TABLE family.
The JVM port of Raptor21.SAP.RFC. A separate
repository because it is a separate toolchain — Gradle, the JDK, Maven Central — with its own release
cadence. The wire behaviour is the .NET library's, deliberately: everything measured there against live
systems (which read function returns wide enough rows, why an empty TABLES parameter still has to be
declared, what offset paging does to a table being written) is reproduced here rather than rediscovered.
var sap = SapClient.connect(SapDestination.builder()
.name("S4")
.baseUrl("https://s4.example.com:44300")
.user("READER")
.password(password)
.client("100")
.build());
var customers = sap.from(Kna1.ENTITY)
.where(Kna1.Columns.LAND1.eq("TR").and(Kna1.Columns.ERDAT.ge(LocalDate.of(2024, 1, 1))))
.select(Kna1.Columns.KUNNR, Kna1.Columns.NAME1, Kna1.Columns.ORT01)
.take(5)
.list();where is sent as SAP's OPTIONS clause and select as its field list, so filtering and projection
happen in SAP rather than after the rows arrive. There is no LINQ on the JVM, so where the .NET library
translates expression trees, this one exposes the same translation as a typed condition API — eq,
between, in, like — on the generated column definitions. A condition SAP cannot answer correctly
is refused while the query is built, never silently: a filter on a column whose conversion exit depends
on the system's own customising throws instead of returning confident, wrong rows.
Kna1 above is generated. The scaffolder ships with the .NET package and gained a Java target:
dotnet <package>/tools/net10.0/Raptor21.SAP.RFC.Tool.dll scaffold \
--tables KNA1,TVKO --target java --out src/main/java/com/acme/sap --namespace com.acme.sap
One scaffolder for every language on purpose. The Data Dictionary pipeline — one round trip per table, conversion exits, reference fields, the domain test that tells a timestamp from a quantity — lives once, and each language is only a renderer at the end of it. The generated file is ordinary source: read it, review it, commit it. Every column carries what the dictionary said about it, including whether a conversion exit applies and what this library will do about it.
No .NET on the machine? The same tool ships as a native, self-contained binary (~7 MB) on each release
of the .NET repository — raptor21-sap-rfc-tool-<platform> under
releases. gradlew fetchScaffolder
downloads the right one for this machine into build/scaffolder/ and prints where it landed; run it
directly with the same arguments as above, no runtime required.
Ported from measurement, not from documentation:
- ALPHA and NUMC padding. Customer 12345 is stored as
0000012345; filters are padded for you, and a front-anchoredLIKEon a padded column is refused because no rewriting of it means what it looks like it means. - Currency scale. A
CURRcolumn is stored at two decimals whatever the currency is;TCURXnames the exceptions. The library readsTCURXonce per destination and scales amounts by the currency their own row carries — a stored10.00in yen is ¥1000. Selecting an amount pulls its currency column into the request automatically. - Read function discovery.
RFC_READ_TABLEstops at roughly 800 characters per row; the Data Services variants go to 30 000. The widest is probed first and the answer remembered per destination. - Paging. Every page asks for the same
ROWCOUNT, including the last — shrinking the final request moves the window and returns rows twice. Offset paging is only stable while the table is not being written, and the streaming API's documentation says so rather than hiding it. - End of day. SAP writes
240000intoTIMScolumns to mean the end of a day. It reads asSapTimes.END_OF_DAYand renders back as240000, so it round-trips instead of shifting silently to 23:59:59.
- Java 17 or newer. No dependencies: the transport is
java.net.http, the values arejava.timeandjava.math. - A SAP system whose SOAP RFC endpoint (
/sap/bc/soap/rfc) is reachable, and a user withS_RFCauthorisation for the table-reading function modules.
gradlew build
MIT — see LICENSE.
Raptor21 SAP RFC is an independent, community-developed library. It is not affiliated with, sponsored by, or endorsed by SAP SE. SAP, SAP S/4HANA and ABAP are trademarks or registered trademarks of SAP SE (or an SAP affiliate company) in Germany and other countries. This library is designed for use with SAP software and is not an SAP product.