Differences in handling of BNodes between SNARK and RDF4J APIs


Whilst testing Stardog 7 (same behaviour in v6.1.2 as far as I can see), there are some differences in passing through query bindings that are BNodes. If using the SNARK API, it works as expected. If using the RDF4J API layer, then I get no results

When using the data below

@prefix : <http://something.com/bnode-test#> .

[] a :Country ;
   :name 'UK' ;
   :currency 'Sterling' ;
   :languages 'English', 'Welsh', 'Gaelic', 'Kernow' .

And then using the test code, I'd expect 4 results for each run - but get 0 for the RDF4J version

import com.complexible.stardog.api.Connection;
import com.complexible.stardog.api.ConnectionConfiguration;
import com.complexible.stardog.api.SelectQuery;
import com.complexible.stardog.rdf4j.StardogRepository;
import com.complexible.stardog.rdf4j.StardogRepositoryConnection;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;

public class BNodeTest {

    private static final String GET_COUNTRY =
            "PREFIX : <http://something.com/bnode-test#> " +
                    "select distinct ?c { ?c a :Country ; :name 'UK' }";

    private static final String GET_DETAILS =
            "PREFIX : <http://something.com/bnode-test#> " +
            "select distinct ?currency ?language { ?it a :Country ; :currency ?currency ; :languages ?language }";

    public static void main(String[] args) {

    private static void viaRDF4J() {
        StardogRepository repository = new StardogRepository("http://localhost:5820/bnode-test");

        try (StardogRepositoryConnection connection = repository.getConnection()) {
            try (TupleQueryResult pops = connection.prepareTupleQuery(GET_COUNTRY).evaluate()) {
                Value country = pops.next().getValue("c");
                System.out.printf("With Country: %s\n", country);

                TupleQuery withCountry = connection.prepareTupleQuery(GET_DETAILS);
                withCountry.setBinding("it", country);
                try (TupleQueryResult bindings = withCountry.evaluate()) {
                    while (bindings.hasNext()) {
                        BindingSet next = bindings.next();
                        for (String name : next.getBindingNames()) {
                            Value value = next.getValue(name);
                            System.out.printf("\t\t%s = %s\n", name, value);


    private static void viaSnark() {
        try (Connection connection = connection()) {
                    .map(b -> b.get("c"))
                    .forEach(country -> {
                        System.out.printf("With Country: %s\n", country);

                        SelectQuery withCountry = connection.select(GET_DETAILS)
                                .parameter("it", country);

                        withCountry.execute().stream().forEach(bindings -> {
                            System.out.printf("\t%s\n", bindings);

    private static Connection connection() {
        return ConnectionConfiguration
                .credentials("admin", "admin")

The second run gives ::bnode_873653f4_39a0_4f34_983d_c5431fd0b79b_7059737 for the bnode which looks like a double anonymisation - if that's such a thing :wink:


Hi Rory, and welcome!

This is indeed a bug in our RDF4J handling. I've located the root cause of it (specifically having to do with TupleQuery#setBinding(BNode) and will create a ticket to get the fix into our next release. Thanks for the report!

Just checking - was this fixed in 6.1.3 under RDF4J connector improperly binding BNodes to query variables (#7001)

If so, awesome. Thanks

Yes, 7001 was indeed the ticket created for this fix!