Search code examples
sqlignite

Issue with running SQL Scan queries in Apache Ignite in clientmode


I am trying to start testing SQL in Apache Ignite using the following code.

    public void testSQLDatabase(){
        CacheConfiguration<Long, Person> cacheCfg = new CacheConfiguration<>();
        cacheCfg.setName("mycache");
        cacheCfg.setCacheMode(CacheMode.PARTITIONED);
        cacheCfg.setIndexedTypes(Long.class, Person.class);

// Setting up query entity.
        QueryEntity queryEntity = new QueryEntity();

        queryEntity.setKeyType(Long.class.getName());
        queryEntity.setValueType(Person.class.getName());

// Listing query fields.
        LinkedHashMap<String, String> fields = new LinkedHashMap();

        fields.put("id", Long.class.getName());
        fields.put("orgId", Long.class.getName());
        fields.put("firstName", String.class.getName());
        fields.put("lastName", String.class.getName());
        fields.put("resume", String.class.getName());
        fields.put("salary", Double.class.getName());

        queryEntity.setFields(fields);

// Listing indexes.
        Collection<QueryIndex> indexes = new ArrayList<>(3);

        indexes.add(new QueryIndex("id"));
        indexes.add(new QueryIndex("orgId"));
        indexes.add(new QueryIndex("salary"));

        queryEntity.setIndexes(indexes);
        cacheCfg.setQueryEntities(Arrays.asList(queryEntity));

        IgniteCache<Long, Person> cache = ignite.getOrCreateCache(cacheCfg);
        cache.clear();

        for(long iCount = 0; iCount < 10000; iCount++) {
            Person person = new Person();
            person.setValues(iCount, 0, "a", "a", "asdf", iCount*100);
            cache.put(iCount, person);
            System.out.println("Got back " + cache.get(iCount).toString());
        }

        IgniteBiPredicate<Long, Person> filter = new IgniteBiPredicate<Long, Person>() {
            @Override public boolean apply(Long key, Person p) {
                return p.getSalary() > 10000d;
            }
        };

        try (QueryCursor cursor = cache.query(new ScanQuery(filter))) {
            System.out.println(cursor.toString());
            for (Object p : cursor)
                System.out.println(p.toString());
        }
    }

   public class Person implements Serializable {
        /**
         * Person ID (indexed).
         */
        @QuerySqlField(index = true)
        private long id;

        /**
         * Organization ID (indexed).
         */
        @QuerySqlField(index = true)
        private long orgId;

        /**
         * First name (not-indexed).
         */
        @QuerySqlField
        private String firstName;

        /**
         * Last name (not indexed).
         */
        @QuerySqlField
        private String lastName;

        /**
         * Resume text (create LUCENE-based TEXT index for this field).
         */
        @QueryTextField
        private String resume;

        /**
         * Salary (indexed).
         */
        @QuerySqlField(index = true)
        private double salary;

        public void setValues(long id, long orgId, String firstName, String lastName, String resume, double salary){
            this.id = id;
            this.orgId = orgId;
            this.firstName = firstName;
            this.lastName = lastName;
            this.resume = resume;
            this.salary = salary;
        }

        public long getId() {
            return id;
        }

        public void setId(long id) {
            this.id = id;
        }

        public long getOrgId() {
            return orgId;
        }

        public void setOrgId(long orgId) {
            this.orgId = orgId;
        }

        public String getFirstName() {
            return firstName;
        }

        public void setFirstName(String firstName) {
            this.firstName = firstName;
        }

        public String getLastName() {
            return lastName;
        }

        public void setLastName(String lastName) {
            this.lastName = lastName;
        }

        public String getResume() {
            return resume;
        }

        public void setResume(String resume) {
            this.resume = resume;
        }

        public double getSalary() {
            return salary;
        }

        public void setSalary(double salary) {
            this.salary = salary;
        }
    }

But I get an exception thrown in the last where I try to go over the cursor with after the scan query.

java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
Caused by: javax.cache.CacheException: class org.apache.ignite.IgniteCheckedException: Query execution failed: GridCacheQueryBean [qry=GridCacheQueryAdapter [type=SCAN, clsName=null, clause=null, filter=co.near.ignite.MainExperiment$1@4c1d79bc, part=null, incMeta=false, metrics=GridCacheQueryMetricsAdapter [minTime=0, maxTime=0, sumTime=0, avgTime=0.0, execs=0, completed=0, fails=0], pageSize=1024, timeout=0, keepAll=true, incBackups=false, dedup=false, prj=null, keepBinary=false, subjId=ca184604-5d57-4549-a2a2-b8601d9062ab, taskHash=0], rdc=null, trans=null]
        at org.apache.ignite.internal.processors.cache.GridCacheUtils.convertToCacheException(GridCacheUtils.java:1618)
        ... 6 more
Caused by: class org.apache.ignite.IgniteCheckedException: Query execution failed: GridCacheQueryBean [qry=GridCacheQueryAdapter [type=SCAN, clsName=null, clause=null, filter=co.near.ignite.MainExperiment$1@4c1d79bc, part=null, incMeta=false, metrics=GridCacheQueryMetricsAdapter [minTime=0, maxTime=0, sumTime=0, avgTime=0.0, execs=0, completed=0, fails=0], pageSize=1024, timeout=0, keepAll=true, incBackups=false, dedup=false, prj=null, keepBinary=false, subjId=ca184604-5d57-4549-a2a2-b8601d9062ab, taskHash=0], rdc=null, trans=null]
        at org.apache.ignite.internal.processors.cache.query.GridCacheQueryFutureAdapter.checkError(GridCacheQueryFutureAdapter.java:267)
        at org.apache.ignite.internal.processors.cache.query.GridCacheQueryFutureAdapter.internalIterator(GridCacheQueryFutureAdapter.java:325)
        at org.apache.ignite.internal.processors.cache.query.GridCacheQueryFutureAdapter.next(GridCacheQueryFutureAdapter.java:171)
        ... 11 more
Caused by: class org.apache.ignite.IgniteCheckedException: Failed to execute query on node [query=GridCacheQueryBean [qry=GridCacheQueryAdapter [type=SCAN, clsName=null, clause=null, filter=co.near.ignite.MainExperiment$1@4c1d79bc, part=null, incMeta=false, metrics=GridCacheQueryMetricsAdapter [minTime=0, maxTime=0, sumTime=0, avgTime=0.0, execs=0, completed=0, fails=0], pageSize=1024, timeout=0, keepAll=true, incBackups=false, dedup=false, prj=null, keepBinary=false, subjId=ca184604-5d57-4549-a2a2-b8601d9062ab, taskHash=0], rdc=null, trans=null], nodeId=06118f33-33b0-4483-bab2-fcc2306a4053]
        at org.apache.ignite.internal.processors.cache.query.GridCacheQueryFutureAdapter.onPage(GridCacheQueryFutureAdapter.java:390)
        at org.apache.ignite.internal.managers.communication.GridIoManager.access$1800(GridIoManager.java:103)
        at org.apache.ignite.internal.managers.communication.GridIoManager$6.run(GridIoManager.java:972)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        ... 1 more
Caused by: class org.apache.ignite.IgniteCheckedException: co.near.ignite.MainExperiment$Person
        at org.apache.ignite.internal.util.IgniteUtils.cast(IgniteUtils.java:7005)
        at org.apache.ignite.internal.util.future.GridFutureAdapter.get0(GridFutureAdapter.java:166)
        at org.apache.ignite.internal.util.future.GridFutureAdapter.get(GridFutureAdapter.java:115)
        at org.apache.ignite.internal.processors.cache.query.GridCacheQueryManager$CachedResult.iterator(GridCacheQueryManager.java:2825)
        at org.apache.ignite.internal.processors.cache.query.GridCacheQueryManager.runQuery(GridCacheQueryManager.java:1390)
        ... 3 more
Caused by: java.lang.ClassNotFoundException: co.near.ignite.MainExperiment$Person
        at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
        ... 14 more

Since I am just started trying out Apache Ignite, I am definitely doing something obviously wrong. It would be great if you could let me know how to fix this.

Also I am running this code in client mode and not as server. A 3-node cluster is running separately.


Solution

  • You're running a predicate-based SCAN query. This query invokes the filter you provide on server nodes, so that only the data you're interested in is returned. Your implementation expects the Person class to be there, so you get this error. There are two options to fix it:

    • (recommended) Use withKeepBinary() flag and BinaryObject instead of Person object. See scanQuery() method in [1] for an example.
    • Add Person class to classpath of all server nodes.

    [1] https://github.com/apache/ignite/blob/master/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheQueryExample.java