Experiment with Embedded Solr in java and C
Solr is poster boy in search market . Generally it is used by running as HTTP server and making queries .
I was more interested in running it in embedded manner and getting results via JNI .
Following you will find the code for doing same and some problems you might face ( with solutions :) ) .
Getting the embedded solr working
String solrDir = "/Users/TheRoot/Downloads/solr-4.7.0/example/solr/";
container = new CoreContainer(solrDir);
container.load();
server = new EmbeddedSolrServer(container, "collection1");
This will get your basic EmbeddedSolr up and running .
Next if you want to make query and get response from the solr ; you can use the following function .
public static String query(String qstring){
String output = null;
ModifiableSolrParams solrParams = new ModifiableSolrParams();
System.out.println(qstring);
solrParams.add(CommonParams.Q, qstring);
QueryResponse queryResponse = null;
try {
queryResponse = server.query(solrParams);
} catch (SolrServerException e) {
e.printStackTrace();
}
for (SolrDocument document : queryResponse.getResults()) {
output += (document.getFieldValueMap().toString());
}
System.out.println(output);
return output;
}
Similary we can update values , Index solr , query it etc ..
The other part of the experiment is getting C to talk to java via JNI .
First create a virtual java machine inside C
JNIEnv* create_vm(JavaVM **jvm)
{
JNIEnv* env;
JavaVMInitArgs args;
JavaVMOption options;
args.version = JNI_VERSION_1_6;
args.nOptions = 1;
options.optionString = "-Djava.class.path=/Users/TheRoot/Documents/workspac[...ALL REQUIRED JARS...]]7.0/dist/solrj-lib/noggit-0.5.jar";
args.options = &options;
args.ignoreUnrecognized = 0;
int rv;
rv = JNI_CreateJavaVM(jvm, (void**)&env, &args);
if (rv < 0 || !env)
printf("JVM launch failed%d\n",rv);
else
printf("Launched JVM\n");
return env;
}
Note : If you do not give path properly in options.optionStrings you will get error something similar to
Invalid memory access of location 0x0 rip=0xADDR
Now call java function from C ..
EmbeddedSolrExample_Class = (*env)->FindClass(env, "EmbeddedSolrExample");
main_method = (*env)->GetStaticMethodID(env, EmbeddedSolrExample_Class, "main", "([Ljava/lang/String;)V");
(*env)->CallStaticVoidMethod(env, EmbeddedSolrExample_Class, main_method, NULL); // Initialize the embedded solr
One thing you might notice is 4th parameter “([Ljava/lang/String;)V” of GetStaticMethodID function . This is signature of any function in java , this has to be specific to the function input and return value , for example for the “main” function “([Ljava/lang/String;)V” is the signature . You can get this value easily using “javap” . Once you have made .class file from your .java file which you want to bind in c , run the following command :
javap -s myclass.class
This will give output something like
Compiled from "EmbeddedSolrExample.java"
public class EmbeddedSolrExample extends java.lang.Object{
static org.apache.solr.core.CoreContainer container;
Signature: Lorg/apache/solr/core/CoreContainer;
static org.apache.solr.client.solrj.embedded.EmbeddedSolrServer server;
Signature: Lorg/apache/solr/client/solrj/embedded/EmbeddedSolrServer;
public EmbeddedSolrExample();
Signature: ()V
public static void main(java.lang.String[]) throws java.lang.Exception;
Signature: ([Ljava/lang/String;)V
public static java.lang.String query(java.lang.String);
Signature: (Ljava/lang/String;)Ljava/lang/String;
public static void entervalues(java.lang.String, int, java.lang.String) throws java.lang.Exception;
Signature: (Ljava/lang/String;ILjava/lang/String;)V
public static void close();
Signature: ()V
}
You can clearly see the signatures here .
Thats it , we now have an application with solr search embedded into it , without the need of running solr http server .
You can get the full code at
https://gist.github.com/nautical/9859418
https://gist.github.com/nautical/9859452