couchbaselabs / TouchDB-Android

CouchDB-compatible mobile database; Android version

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Creating inline views using Ektorp CouchDbRepositorySupport throws NullPointerException when compiling view

bhaskarmurthy opened this issue · comments

I'm using inline views provided by the CouchDbRepositorySupport class from Ektorp.
Whenever the inline view is reference, I get a NullReferenceException at the following line:

TDRouter.java:L1327

        TDViewMapBlock mapBlock = TDView.getCompiler().compileMapFunction(mapSource, language);

Checking the debugger tells me that TDView.getCompiler() is null.

My view repository looks like:

public class BadgeRepository extends CouchDbRepositorySupport<Badge> {
    public BadgeRepository(CouchDbConnector db) {
        super(Badge.class, db);
        initStandardDesignDocument();
    }

    @View(name = "byId", map = "function(doc) { if (doc.groupId && doc.userId) emit([doc.groupId,doc.userId]) }")
    public Badge get(String groupId, String userId) {
        try {
            ViewQuery query = createQuery("byId")
                    .key(ComplexKey.of(groupId, userId));
            List<Badge> result = db.queryView(query, Badge.class);
            if (result.size() > 0) {
                return result.get(0);
            }
        } catch (DocumentNotFoundException e) {
            return null;
        }

        return null;
    }
}

Is this an issue with the TDRouter for TouchDB-Android? or something related to Ektorp?

inline views is not something I've ever seen working with TouchDB-Android. That doesn't mean it can't work, just that you'll have to help figure out what is going wrong.

I would recommend 2 things.

  1. Provide the complete stack trace of the error.
  2. Try and get it working without inline views first (manually creating the design document). Knowing that this much works first will help narrow down where the problems may be.

I tried creating the view manually using TDDatabase.getViewName(...) method.
If I try to use the queryView("all") method, I get no results.
However, the getAll() method returns results, which I can see are results from the whole db, not just the "all" view for the design document.

This means that the "all" view that I created didn't actually get saved to the db somehow.

My code to create the view:

db.getViewNamed("Badge/all").setMapReduceBlocks(new TDViewMapBlock() {

            @Override
            public void map(Map<String, Object> document, TDViewMapEmitBlock emitter) {
                Object type = document.get("type");
                Object id = document.get("_id");
                Object groupId = document.get("groupId");
                Object userId = document.get("userId");

                if (type != null && type.equals("Badge")) {
                    emitter.emit(ComplexKey.of(groupId, userId), id);
                }
            }
        }, null, "1.0");

If I use the inline view, the exception stack trace is:

02-04 00:59:42.220: E/TDDatabase(22962): Exception in TDRouter
02-04 00:59:42.220: E/TDDatabase(22962): java.lang.reflect.InvocationTargetException
02-04 00:59:42.220: E/TDDatabase(22962):    at java.lang.reflect.Method.invokeNative(Native Method)
02-04 00:59:42.220: E/TDDatabase(22962):    at java.lang.reflect.Method.invoke(Method.java:511)
02-04 00:59:42.220: E/TDDatabase(22962):    at com.couchbase.touchdb.router.TDRouter.start(TDRouter.java:390)
02-04 00:59:42.220: E/TDDatabase(22962):    at com.couchbase.touchdb.ektorp.TouchDBHttpClient.executeRequest(TouchDBHttpClient.java:191)
02-04 00:59:42.220: E/TDDatabase(22962):    at com.couchbase.touchdb.ektorp.TouchDBHttpClient.get(TouchDBHttpClient.java:68)
02-04 00:59:42.220: E/TDDatabase(22962):    at com.couchbase.touchdb.ektorp.TouchDBHttpClient.getUncached(TouchDBHttpClient.java:76)
02-04 00:59:42.220: E/TDDatabase(22962):    at org.ektorp.http.RestTemplate.getUncached(RestTemplate.java:26)
02-04 00:59:42.220: E/TDDatabase(22962):    at org.ektorp.impl.StdCouchDbConnector.executeQuery(StdCouchDbConnector.java:410)
02-04 00:59:42.220: E/TDDatabase(22962):    at org.ektorp.impl.StdCouchDbConnector.queryView(StdCouchDbConnector.java:404)
02-04 00:59:42.220: E/TDDatabase(22962):    at com.app.dataaccess.BadgeRepository.get(BadgeRepository.java:24)
02-04 00:59:42.220: E/TDDatabase(22962):    at com.app.test.repository.BadgeRepositoryTest.testInsertRemoveUpdate(BadgeRepositoryTest.java:48)
02-04 00:59:42.220: E/TDDatabase(22962):    at java.lang.reflect.Method.invokeNative(Native Method)
02-04 00:59:42.220: E/TDDatabase(22962):    at java.lang.reflect.Method.invoke(Method.java:511)
02-04 00:59:42.220: E/TDDatabase(22962):    at junit.framework.TestCase.runTest(TestCase.java:168)
02-04 00:59:42.220: E/TDDatabase(22962):    at junit.framework.TestCase.runBare(TestCase.java:134)
02-04 00:59:42.220: E/TDDatabase(22962):    at junit.framework.TestResult$1.protect(TestResult.java:115)
02-04 00:59:42.220: E/TDDatabase(22962):    at junit.framework.TestResult.runProtected(TestResult.java:133)
02-04 00:59:42.220: E/TDDatabase(22962):    at junit.framework.TestResult.run(TestResult.java:118)
02-04 00:59:42.220: E/TDDatabase(22962):    at junit.framework.TestCase.run(TestCase.java:124)
02-04 00:59:42.220: E/TDDatabase(22962):    at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:190)
02-04 00:59:42.220: E/TDDatabase(22962):    at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:175)
02-04 00:59:42.220: E/TDDatabase(22962):    at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555)
02-04 00:59:42.220: E/TDDatabase(22962):    at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1661)
02-04 00:59:42.220: E/TDDatabase(22962): Caused by: java.lang.NullPointerException
02-04 00:59:42.220: E/TDDatabase(22962):    at com.couchbase.touchdb.router.TDRouter.compileView(TDRouter.java:1327)
02-04 00:59:42.220: E/TDDatabase(22962):    at com.couchbase.touchdb.router.TDRouter.queryDesignDoc(TDRouter.java:1367)
02-04 00:59:42.220: E/TDDatabase(22962):    at com.couchbase.touchdb.router.TDRouter.do_GET_DesignDocument(TDRouter.java:1419)
02-04 00:59:42.220: E/TDDatabase(22962):    ... 23 more
@View(name = "byId", map = "function(doc) { if (doc.groupId && doc.userId) emit([doc.groupId,doc.userId]) }")

That’s JavaScript. I don’t think TouchDB/Android supports map functions written in JavaScript; does it, Marty?

Yes it does, provided you include the TouchDB-Android-JavaScript module.

But, I think there is some linkage missing between Ektorp building the
views behind the scenes, creating the design document, and it working end
to end. I think all the pieces are there, but the glue connecting them is
missing. But I haven't walked though this part of the code in a while now.

marty

On Mon, Feb 4, 2013 at 10:59 AM, Jens Alfke notifications@github.comwrote:

@view(name = "byId", map = "function(doc) { if (doc.groupId && doc.userId)
emit([doc.groupId,doc.userId]) }")

That’s JavaScript. I don’t think TouchDB/Android supports map functions
written in JavaScript; does it, Marty?


Reply to this email directly or view it on GitHubhttps://github.com//issues/84#issuecomment-13092909.

For CBLite I had the same problem and as Marty suggested I solved including dependencies versus CBLiteJavascript and setting in my code the Javascript Compiler once before querying first time.

CBLView.setCompiler(new CBLJavaScriptViewCompiler());

the same should work for TouchDB using the relative classes.

My DB is replicated from an apache couchdb, but unfortunately it seems that some views which works fine on apache couchdb doesn't return the results as expected. Are there some known issue with Javascript compiler?

I have only tried playing with a trivial javascript view with a map function and it worked fine for me when I tried to query it from curl. (cblite was running behind LiteServAndroid)

Can you post the following:

  • Your design doc which contains the map function
  • An example doc
  • Details on how you are querying the view which shows any parameters you are using