diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 16c5367fc..ea60dde62 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -55,10 +55,6 @@ jobs:
if [ $JELLY_VERSION = "refs/heads/main" ]; then
JELLY_VERSION="dev"
fi
- # For Jena 5.5.0
- sbt "integrationTests/testOnly *ProtocolConformanceSpec -- -z Jena -C eu.neverblink.jelly.integration_tests.util.ConformanceReporter"
- # Jena 5.3.0 and the rest
- sed -i "s/lazy val jenaV = .*/lazy val jenaV = \"5.3.0\"/g" build.sbt
sbt "integrationTests/testOnly *ProtocolConformanceSpec -- -C eu.neverblink.jelly.integration_tests.util.ConformanceReporter"
cd integration-tests/target
tar -czf conformance_reports.tar.gz reports/
diff --git a/.github/workflows/scala.yml b/.github/workflows/scala.yml
index de2b72876..a3b6b9b00 100644
--- a/.github/workflows/scala.yml
+++ b/.github/workflows/scala.yml
@@ -23,12 +23,11 @@ jobs:
# Tests run on JDK 21 (LTS baseline), 25, and the latest release (26).
# Across those we also exercise the oldest and newest supported Jena/RDF4J versions.
# The dependency is set by default to Jena 5.6.
- # See: https://github.com/Jelly-RDF/jelly-jvm/issues/622
- os: ubuntu-latest
java: 21
- # Jena 5.3.0 is the last version supporting RDF-star.
- # 5.4.0 dropped it in favor of RDF1.2.
- jena_version: "5.3.0"
+ # Jena 5.4.0 is the oldest supported version - it introduced the RDF 1.2 triple term
+ # API that we use, replacing the RDF-star API of 5.3.x and older.
+ jena_version: "5.4.0"
# Test the last RDF4J 4.x version.
rdf4j_version: "4.3.16"
# Jena 6 requires Java 21.
@@ -61,9 +60,8 @@ jobs:
- name: Setup SBT
uses: sbt/setup-sbt@v1
- # This is necessary, as Jena suddenly dropped support for RDF-star in 5.4.0 in favor of RDF1.2.
- # We want to keep RDF-star support a possibility, so we test against Jena 5.3 as well as the latest version.
- # See: https://github.com/Jelly-RDF/jelly-jvm/issues/368
+ # Jena and RDF4J occasionally change their APIs between minor versions, so we test against
+ # the oldest and the newest supported version of each.
- name: Switch Jena and RDF4J versions
shell: bash
run: |
diff --git a/build.sbt b/build.sbt
index 69da9ac5a..46e1555a2 100644
--- a/build.sbt
+++ b/build.sbt
@@ -63,9 +63,7 @@ lazy val commonSettings = Seq(
) ++ wErrorIfCI,
// Explicitly specify the options for javadoc, otherwise sbt will pass all javacOptions to it
// which will cause an error.
- // Exclude org.apache to avoid including JenaCompatHelper.
- // See: https://github.com/Jelly-RDF/jelly-jvm/issues/622
- Compile / doc / javacOptions := Seq("-source", "21", "-exclude", "org.apache"),
+ Compile / doc / javacOptions := Seq("-source", "21"),
assemblyJarName := s"${name.value}.jar",
assemblyMergeStrategy := {
case x if x.endsWith("module-info.class") => MergeStrategy.concat
diff --git a/docs/docs/index.md b/docs/docs/index.md
index 9b380ac66..3a9de5f94 100644
--- a/docs/docs/index.md
+++ b/docs/docs/index.md
@@ -67,7 +67,7 @@ The following table shows the compatibility of the Jelly-JVM implementation with
| Jelly-JVM | Java | Scala | RDF4J | Jena | Pekko | Neo4j |
|:-----------------------------------------------------------------------------------------------------------------------------------------------:|:----:|:-------------------------:|:-----------:|:-------------------------------------:|:-----------------------------------------------------------------------:|:-----------------------------------------------------:|
-| [4.0.x](https://w3id.org/jelly/jelly-jvm/4.0.x)–[**{{ jvm_package_version() }}**](https://w3id.org/jelly/jelly-jvm/{{ jvm_package_version() }}) | 21+ | 3.3.x (LTS)[^2] | 4.3.x–5.x.x | 5.x.x–6.x.x | 1.1.x–1.2.x | {{ neo4j_version('min') }}–{{ neo4j_version('max') }} |
+| [4.0.x](https://w3id.org/jelly/jelly-jvm/4.0.x)–[**{{ jvm_package_version() }}**](https://w3id.org/jelly/jelly-jvm/{{ jvm_package_version() }}) | 21+ | 3.3.x (LTS)[^2] | 4.3.x–5.x.x | 5.4.x–6.x.x | 1.1.x–1.2.x | {{ neo4j_version('min') }}–{{ neo4j_version('max') }} |
| [3.7.x](https://w3id.org/jelly/jelly-jvm/3.7.x) | 17+ | 3.3.x (LTS)[^2] | 4.3.x–5.x.x | 5.x.x–6.x.x | 1.1.x–1.2.x | 5.1.0–5.26.0 |
| [3.5.x](https://w3id.org/jelly/jelly-jvm/3.5.x)–[3.6.x](https://w3id.org/jelly/jelly-jvm/3.6.x) | 17+ | 3.3.x (LTS)[^2] | 4.3.x–5.x.x | 5.x.x | 1.1.x–1.2.x | 5.1.0–5.26.0 |
| [3.0.x](https://w3id.org/jelly/jelly-jvm/3.0.x)–[3.4.x](https://w3id.org/jelly/jelly-jvm/3.4.x) | 17+ | 3.3.x (LTS)[^2] | 5.x.x | 5.x.x | 1.1.x | – |
diff --git a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/patch/impl/JenaImplementation.scala b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/patch/impl/JenaImplementation.scala
index 0c7f6fd28..cc472427c 100644
--- a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/patch/impl/JenaImplementation.scala
+++ b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/patch/impl/JenaImplementation.scala
@@ -4,7 +4,7 @@ import eu.neverblink.jelly.convert.jena.patch.*
import eu.neverblink.jelly.core.patch.JellyPatchOptions
import eu.neverblink.jelly.core.proto.v1.patch.{PatchStatementType, RdfPatchOptions}
import eu.neverblink.jelly.integration_tests.patch.traits.*
-import eu.neverblink.jelly.integration_tests.util.{CompatibilityUtils, TestComparable}
+import eu.neverblink.jelly.integration_tests.util.TestComparable
import org.apache.jena.rdfpatch.text.RDFPatchReaderText
import org.scalatest.matchers.should.Matchers.*
@@ -26,7 +26,8 @@ object JenaImplementation extends RdfPatchImplementation[JenaChangesCollector]:
override def name: String = "Jena"
- override def supportsRdfStar: Boolean = !CompatibilityUtils.jenaVersion54OrHigher
+ // Jena dropped RDF-star in 5.4.0, in favor of RDF 1.2.
+ override def supportsRdfStar: Boolean = false
override def readRdf(in: InputStream, stType: PatchStatementType): JenaChangesCollector =
val collector = JellyPatchOps.changesCollector(stType)
diff --git a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/JenaTestStream.scala b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/JenaTestStream.scala
index 2baa9e046..08da5c94b 100644
--- a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/JenaTestStream.scala
+++ b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/JenaTestStream.scala
@@ -3,7 +3,6 @@ package eu.neverblink.jelly.integration_tests.rdf
import eu.neverblink.jelly.convert.jena.{JenaAdapters, JenaConverterFactory}
import eu.neverblink.jelly.core.proto.v1.{RdfStreamFrame, RdfStreamOptions}
import eu.neverblink.jelly.core.utils.{QuadExtractor, QuadMaker, TripleExtractor, TripleMaker}
-import eu.neverblink.jelly.integration_tests.util.CompatibilityUtils
import eu.neverblink.jelly.pekko.stream.{DecoderFlow, EncoderFlow, RdfSource, SizeLimiter}
import org.apache.jena.graph.{Node, Triple}
import org.apache.jena.riot.system.AsyncParser
@@ -30,9 +29,10 @@ case object JenaTestStream extends TestStream:
given JenaAdapters.DATASET_GRAPH_ADAPTER.type = JenaAdapters.DATASET_GRAPH_ADAPTER
given JenaAdapters.MODEL_ADAPTER.type = JenaAdapters.MODEL_ADAPTER
- override def supportsRdf12: Boolean = CompatibilityUtils.jenaVersion54OrHigher
+ override def supportsRdf12: Boolean = true
- override def supportsRdfStar: Boolean = !CompatibilityUtils.jenaVersion54OrHigher
+ // Jena dropped RDF-star in 5.4.0, in favor of RDF 1.2.
+ override def supportsRdfStar: Boolean = false
override def tripleSource(
is: InputStream,
diff --git a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaReactiveSerDes.scala b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaReactiveSerDes.scala
index 1820ce75c..1968a09c4 100644
--- a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaReactiveSerDes.scala
+++ b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaReactiveSerDes.scala
@@ -3,7 +3,6 @@ package eu.neverblink.jelly.integration_tests.rdf.io
import eu.neverblink.jelly.convert.jena.{JenaAdapters, JenaConverterFactory}
import eu.neverblink.jelly.core.JellyOptions
import eu.neverblink.jelly.core.proto.v1.{PhysicalStreamType, RdfStreamOptions}
-import eu.neverblink.jelly.integration_tests.util.CompatibilityUtils
import eu.neverblink.jelly.pekko.stream.*
import org.apache.jena.graph.{Node, Triple}
import org.apache.jena.query.Dataset
@@ -26,12 +25,12 @@ class JenaReactiveSerDes(implicit mat: Materializer)
val name = "Reactive writes (Apache Jena)"
- override def supportsRdf12: Boolean = CompatibilityUtils.jenaVersion54OrHigher
+ override def supportsRdf12: Boolean = true
- override def supportsRdfStar: Boolean = !CompatibilityUtils.jenaVersion54OrHigher
+ // Jena dropped RDF-star in 5.4.0, in favor of RDF 1.2.
+ override def supportsRdfStar: Boolean = false
- override def supportsRdfStar(physicalStreamType: PhysicalStreamType): Boolean =
- !CompatibilityUtils.jenaVersion54OrHigher
+ override def supportsRdfStar(physicalStreamType: PhysicalStreamType): Boolean = false
override def readTriplesW3C(is: InputStream): Model = JenaSerDes.readTriplesW3C(is)
diff --git a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaSerDes.scala b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaSerDes.scala
index e41345c5d..ae3ba1671 100644
--- a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaSerDes.scala
+++ b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaSerDes.scala
@@ -3,7 +3,7 @@ package eu.neverblink.jelly.integration_tests.rdf.io
import eu.neverblink.jelly.convert.jena.riot.{JellyFormatVariant, JellyLanguage}
import eu.neverblink.jelly.core.JellyOptions
import eu.neverblink.jelly.core.proto.v1.RdfStreamOptions
-import eu.neverblink.jelly.integration_tests.util.{CompatibilityUtils, Measure}
+import eu.neverblink.jelly.integration_tests.util.Measure
import org.apache.jena.query.{Dataset, DatasetFactory}
import org.apache.jena.rdf.model.{Model, ModelFactory}
import org.apache.jena.riot.*
@@ -17,9 +17,10 @@ given Measure[Dataset] = (ds: Dataset) => ds.asDatasetGraph().find().asScala.siz
object JenaSerDes extends NativeSerDes[Model, Dataset]:
val name = "Jena"
- override def supportsRdf12: Boolean = CompatibilityUtils.jenaVersion54OrHigher
+ override def supportsRdf12: Boolean = true
- override def supportsRdfStar: Boolean = !CompatibilityUtils.jenaVersion54OrHigher
+ // Jena dropped RDF-star in 5.4.0, in favor of RDF 1.2.
+ override def supportsRdfStar: Boolean = false
override def readTriplesW3C(is: InputStream): Model =
val m = ModelFactory.createDefaultModel()
diff --git a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaStreamSerDes.scala b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaStreamSerDes.scala
index 1c327a169..c46e0aaab 100644
--- a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaStreamSerDes.scala
+++ b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaStreamSerDes.scala
@@ -4,8 +4,8 @@ import eu.neverblink.jelly.convert.jena.riot.JellyLanguage
import eu.neverblink.jelly.core.JellyOptions
import eu.neverblink.jelly.core.proto.v1.{PhysicalStreamType, RdfStreamOptions}
import eu.neverblink.jelly.integration_tests.rdf.util.riot.TestRiot
-import eu.neverblink.jelly.integration_tests.util.{CompatibilityUtils, Measure}
-import org.apache.jena.graph.{JenaCompatHelper, Node, Triple}
+import eu.neverblink.jelly.integration_tests.util.Measure
+import org.apache.jena.graph.{Node, Triple}
import org.apache.jena.riot.lang.LabelToNode
import org.apache.jena.riot.system.{StreamRDFLib, StreamRDFWriter}
import org.apache.jena.riot.{RDFParser, RIOT}
@@ -26,12 +26,12 @@ object JenaStreamSerDes
override def name: String = "Jena (StreamRDF)"
- override def supportsRdf12: Boolean = CompatibilityUtils.jenaVersion54OrHigher
+ override def supportsRdf12: Boolean = true
- override def supportsRdfStar: Boolean = !CompatibilityUtils.jenaVersion54OrHigher
+ // Jena dropped RDF-star in 5.4.0, in favor of RDF 1.2.
+ override def supportsRdfStar: Boolean = false
- override def supportsRdfStar(physicalStreamType: PhysicalStreamType): Boolean =
- !CompatibilityUtils.jenaVersion54OrHigher
+ override def supportsRdfStar(physicalStreamType: PhysicalStreamType): Boolean = false
override def readTriplesW3C(is: InputStream): Seq[Triple] =
val sink = SinkSeq[Triple]()
@@ -215,7 +215,7 @@ object JenaStreamSerDes
override def getBlankNodeLabel(node: Node): String = node.getBlankNodeLabel
- override def isNodeTriple(node: Node): Boolean = JenaCompatHelper.isNodeTriple(node)
+ override def isNodeTriple(node: Node): Boolean = node.isTripleTerm
override def iterateTerms(node: Triple | Quad): Seq[Node] =
node match {
diff --git a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/util/JenaToRdf4jAdapter.scala b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/util/JenaToRdf4jAdapter.scala
index 49d43fb48..fc04ff0cd 100644
--- a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/util/JenaToRdf4jAdapter.scala
+++ b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/util/JenaToRdf4jAdapter.scala
@@ -1,6 +1,6 @@
package eu.neverblink.jelly.integration_tests.rdf.util
-import org.apache.jena.graph.{JenaCompatHelper, Node, Triple}
+import org.apache.jena.graph.{Node, Triple}
import org.apache.jena.riot.system.StreamRDF
import org.apache.jena.sparql.core.Quad
import org.eclipse.rdf4j.model.{IRI, Resource, Value}
@@ -17,7 +17,7 @@ class JenaToRdf4jAdapter(delegate: RDFHandler) extends StreamRDF {
def makeResource(n: Node): Resource = {
if n.isBlank then vf.createBNode(n.getBlankNodeLabel)
- else if JenaCompatHelper.isNodeTriple(n) then {
+ else if n.isTripleTerm then {
val t = n.getTriple
vf.createTriple(
makeResource(t.getSubject),
diff --git a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/util/riot/LangNTupleGeneralized.scala b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/util/riot/LangNTupleGeneralized.scala
index a3a56de55..73a308d0b 100644
--- a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/util/riot/LangNTupleGeneralized.scala
+++ b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/util/riot/LangNTupleGeneralized.scala
@@ -1,6 +1,6 @@
package eu.neverblink.jelly.integration_tests.rdf.util.riot
-import org.apache.jena.graph.{JenaCompatHelper, Node, Triple}
+import org.apache.jena.graph.{Node, NodeFactory, Triple}
import org.apache.jena.riot.lang.LangNTuple
import org.apache.jena.riot.system.{ParserProfile, StreamRDF}
import org.apache.jena.riot.tokens.{StringType, Token, TokenType, Tokenizer}
@@ -69,4 +69,4 @@ abstract class LangNTupleGeneralized[T](tokens: Tokenizer, profile: ParserProfil
val x = nextToken
if ((x.getType ne TokenType.GT2) && (x.getType ne TokenType.R_TRIPLE))
exception(x, "Triple term not terminated by >>: %s", x)
- JenaCompatHelper.createTripleNode(t)
+ NodeFactory.createTripleTerm(t)
diff --git a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/util/CompatibilityUtils.scala b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/util/CompatibilityUtils.scala
deleted file mode 100644
index 54392ecfd..000000000
--- a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/util/CompatibilityUtils.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-package eu.neverblink.jelly.integration_tests.util
-
-import org.apache.jena.Jena
-
-object CompatibilityUtils:
- lazy val jenaVersion54OrHigher: Boolean = {
- val split = Jena.VERSION.split('.')
- split(0).toInt > 5 || split(1).toInt >= 4
- }
diff --git a/jena/src/main/java/eu/neverblink/jelly/convert/jena/JenaDecoderConverter.java b/jena/src/main/java/eu/neverblink/jelly/convert/jena/JenaDecoderConverter.java
index 1253b011e..01d58cb78 100644
--- a/jena/src/main/java/eu/neverblink/jelly/convert/jena/JenaDecoderConverter.java
+++ b/jena/src/main/java/eu/neverblink/jelly/convert/jena/JenaDecoderConverter.java
@@ -4,7 +4,6 @@
import eu.neverblink.jelly.core.utils.QuadMaker;
import eu.neverblink.jelly.core.utils.TripleMaker;
import org.apache.jena.datatypes.RDFDatatype;
-import org.apache.jena.graph.JenaCompatHelper;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.NodeFactory;
import org.apache.jena.graph.Triple;
@@ -46,7 +45,7 @@ public Node makeIriNode(String iri) {
@Override
public Node makeTripleNode(Node s, Node p, Node o) {
- return JenaCompatHelper.createTripleNode(s, p, o);
+ return NodeFactory.createTripleTerm(s, p, o);
}
@Override
diff --git a/jena/src/main/java/eu/neverblink/jelly/convert/jena/JenaEncoderConverter.java b/jena/src/main/java/eu/neverblink/jelly/convert/jena/JenaEncoderConverter.java
index f481241bc..8cee6c3e6 100644
--- a/jena/src/main/java/eu/neverblink/jelly/convert/jena/JenaEncoderConverter.java
+++ b/jena/src/main/java/eu/neverblink/jelly/convert/jena/JenaEncoderConverter.java
@@ -6,7 +6,6 @@
import eu.neverblink.jelly.core.utils.QuadExtractor;
import eu.neverblink.jelly.core.utils.TripleExtractor;
import org.apache.jena.datatypes.xsd.XSDDatatype;
-import org.apache.jena.graph.JenaCompatHelper;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.Triple;
import org.apache.jena.sparql.core.Quad;
@@ -37,7 +36,7 @@ public Object nodeToProto(NodeEncoder encoder, Node node) {
} else {
return encoder.makeLangLiteral(node, node.getLiteralLexicalForm(), lang);
}
- } else if (JenaCompatHelper.isNodeTriple(node)) {
+ } else if (node.isTripleTerm()) {
// RDF-star node
final var t = node.getTriple();
return encoder.makeQuotedTriple(t.getSubject(), t.getPredicate(), t.getObject());
diff --git a/jena/src/main/java/org/apache/jena/graph/JenaCompatHelper.java b/jena/src/main/java/org/apache/jena/graph/JenaCompatHelper.java
deleted file mode 100644
index 8f75a8bb7..000000000
--- a/jena/src/main/java/org/apache/jena/graph/JenaCompatHelper.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.apache.jena.graph;
-
-import eu.neverblink.jelly.core.InternalApi;
-
-/**
- * Hack to avoid very complex dependency and method binding workarounds needed to support
- * Jena 5.3, 5.4, and 6.0 at the same time.
- * This class should be removed as soon as Jena 5.3 support is dropped.
- * See: issue
- */
-@InternalApi
-public final class JenaCompatHelper {
-
- public static boolean isNodeTriple(Node node) {
- return node instanceof Node_Triple;
- }
-
- public static Node createTripleNode(Node s, Node p, Node o) {
- return new Node_Triple(s, p, o);
- }
-
- public static Node createTripleNode(Triple t) {
- return new Node_Triple(t);
- }
-}
diff --git a/jena/src/test/scala/eu/neverblink/jelly/convert/jena/JenaCompatHelperSpec.scala b/jena/src/test/scala/eu/neverblink/jelly/convert/jena/JenaVersionSpec.scala
similarity index 91%
rename from jena/src/test/scala/eu/neverblink/jelly/convert/jena/JenaCompatHelperSpec.scala
rename to jena/src/test/scala/eu/neverblink/jelly/convert/jena/JenaVersionSpec.scala
index 4bb76e816..c7b624836 100644
--- a/jena/src/test/scala/eu/neverblink/jelly/convert/jena/JenaCompatHelperSpec.scala
+++ b/jena/src/test/scala/eu/neverblink/jelly/convert/jena/JenaVersionSpec.scala
@@ -4,7 +4,7 @@ import eu.neverblink.jelly.convert.jena.traits.JenaTest
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
-class JenaCompatHelperSpec extends AnyWordSpec, Matchers, JenaTest:
+class JenaVersionSpec extends AnyWordSpec, Matchers, JenaTest:
val isCi: Boolean = System.getenv("CI") != null
val jenaVersionCI: String = System.getenv("JENA_VERSION")
val jenaVersionFromClass = org.apache.jena.Jena.VERSION