Spymemcached - CouchbaseClient issues

Hi,

We've just updated to the preview-2 version of spymemcached (any chance of getting a detailed list of changes by the way - it changed (and therefore broke) a lot of stuff).

One change is that, in the absence of a viewmode property, or a config.properties file, the view defaults to production. This bring me to our requests:
It would be nice if there was a setter in CouchbaseClient to set the viewmode programmatically rather than having to use the properties file.

More importantly, it would be great if you could change CouchbaseClient to read the file in as a resource using something like:
properties.load(ClassLoader.getSystemResourceAsStream("config.properties"));

That way it only needs to be on the Classpath. Currently it's read in using FileInputStream which means having to deal with actual file locations, always a real pain when writing web apps.

Thanks,
Oli.

1 Answer

« Back to question.

Thanks for the suggestion. I'll add the ability to set the viewmode property programmatically for the 2.8-beta release.

As for changes, we definitely made a few API changes. I'll try to capture them all here, but if I miss something let me know.

The first thing we did was made it so that there is only one query function. Previously, we had three, but now based on how you define your query CouchbaseClient will call the appropriate query function. So we have
HttpFuture asyncQuery(View view, Query query)

instead of

ViewFuture asyncQuery(View view, Query query)
HttpFuture asyncQueryAndExcludeDocs(View view, Query query)
HttpFuture asyncQueryAndReduce(View view, Query query)

We also made all ViewResponse classes (ViewResponseWithDocs, ViewResponseNoDocs, ViewResponseReduced) implement ViewResponse and all classes contain the same functions. What this means to you is that developers only need to be aware of the ViewResponse class.

We also consolidated the Row classes and renamed them. All of the row classes now implement ViewRow and contain all of the Row classes contain the same functions. This means that you only have to deal with one type, ViewRow, when dealing with rows.

I put some examples below of the new API, but first off I want to mention that with this added simplicity you also need to be a little bit more careful about how you use the api. For example, if you do a query that doesn't get the document for each row and you try to access the document in the ViewRow you will get an exception saying that the view doesn't contain documents. This shouldn't present any huge issues for developers, but it does mean that you need to be aware of what type of query you are doing and handle the response appropriately.

Old API:

Query query = new Query();
query.setRange("a", "m");
query.setDescending(false);
 
ViewFuture result = client.query(view, query);
 
ViewResponseWithDocs response;
try {
  response = result.get();
} catch (ExecutionException e) {
  e.printStackTrace();
  continue;
}
 
Iterator<RowWithDocs> itr = response.iterator();
 
while(itr.hasNext()) {
  RowWithDocs row = itr.next();
  String doc = (String)row.getDoc();
  System.out.println(doc);
}

New API:

Query query = new Query();
query.setRange("a", "m");
query.setDescending(false);
query.setIncludeDocs(true);
 
HttpFuture<ViewResponse> result = client.asyncQuery(view, query);
 
ViewResponse response;
try {
  response = result.get();
} catch (ExecutionException e) {
  e.printStackTrace();
  continue;
}
 
Iterator<ViewRow> itr = response.iterator();
 
while(itr.hasNext()) {
  ViewRow row = itr.next();
  String doc = (String)row.getDoc();
  System.out.println(doc);
}

If you wish to track your improvement request I have filed it here.
http://www.couchbase.com/issues/browse/SPY-50

Let me know if you have any other questions.

Thanks Mike

Much appreciated.

If you could also find your way to changing the use of FileInputStream in CouchbaseClient to a ClassLoader based approach (as above) for the beta that would be a lot nicer.

I just checked a fix into our code review system for this. It will be available in the beta release. Now the properties have a priority as follows:

1. Specified in user code - System.setProperty(2)
2. Specified on the command line
3. Specified in the cbclient.properties file.

And the file must be located on the classpath to be found.

URL url = ClassLoader.getSystemResource("cbclient.properties");
properties.load(new FileInputStream(new File(url.getFile())));

I don't understand why you would code it this way, why not do a:

getClass().getResourceAsStream("/cbclient.properties");

If you have already implemented it this way, it would explain why in my patched version it does not find the file whilst running under Tomcat.

The patch I was referring to was put into the master branch and will be part of the developer-preview-3 release. I coded it this way so that the file could be located by adding the properties file path to the java classpath. If this is causing issues for you with Tomcat you can also use the System.setProperty(2) function in your application code.

What is 'System.setProperty(2)' referring to, it is not valid java.
To set a system property you need a key and a value.
We need to know what key and value to set and what they mean.

System.setProperty(2) means the System.setProperty() function which takes 2 parameters and as you mentioned above those parameters are the key and the value. In this case your key is "viewmode" and your value can be either "development" or "production". So doing System.setProperty("viewmode", "development") will put your client in development mode.

The second options that this change makes possible is being able to set this property on the command line. If you add the argument below you will also be able to set the viewmode property.

-Dviewmode=development

The third option you have is to specify this property in a properties file. That file must be named cbclient.properties and it must be on your java classpath for it to be found. If you create a file that has the following on a single line you will also be able to set the viewmode.

viewmode=development

Please also note that that the priority for setting properties is

1. Set in code - System.setProperty(2)
2. Set on command line
3. Set in properties file

So if you we to use all of these options then whatever was set in the code would win. Also, make sure that if you set this property in the code that it is set before you create your CouchbaseClient.

For information on development/production mode and which one you should be using it would probably be best to watch this video that was put together by one of our solutions architects.

http://info.couchbase.com/Couchbase2BetaWebinars-A.html

Perfect, thanks for the info Mike!