Could not find implementation class: "cassandra" - java

I'm trying to connect to Titan backed with Cassandra (installed with the Rexster Titan-Server package) via Titan-Node.
I get the error...
java.lang.IllegalArgumentException: Could not find implementation
class: "cassandra"
... when I run the following code....
var Titan = require('titan-node');
var gremlin = new Titan.Gremlin({ loglevel: 'OFF' });
var TitanFactory = gremlin.java.import('com.thinkaurelius.titan.core.TitanFactory');
var graph = TitanFactory.openSync('titan.config');
Config:
storage.directory = "/tmp/titan"
storage.backend = "cassandra"
storage.hostname = "127.0.0.1"
storage.port = 9160
Any ideas?
I seem to have the required .jar within my Titan installation folder and also in the target/dependency folder within the Titan-Node package.
Why can't Java find the file? Is there a missing classpath entry? If so would it need to be set for the database or for node? I figure it would be node because that's the app trying to load the class.
EDIT
Dan's suggestion gave me....
'java.lang.IllegalArgumentException: Could not find implementation
class:
"com.thinkaurelius.titan.diskstorage.cassandra.thrift.CassandraThriftStoreManager"'
...and...
'java.lang.IllegalArgumentException: Could not find implementation
class:
"com.thinkaurelius.titan.diskstorage.cassandra.astyanax.AstyanaxStoreManager"'
...respectively.
In fact whatever value you set storage.backend to in the config, that's the name of the class it can't find an implementation for that it reports in the exception message.
If you look in the code here...
https://github.com/thinkaurelius/titan/blob/master/titan-core/src/main/java/com/thinkaurelius/titan/diskstorage/Backend.java
...the instantiate method that is throwing the exception uses the method parameter clazzname in the message which is passed in by the call in getImplementationClass. The latter ought to be looking up the class to load via the key set in storage.backend but oddly it doesn't seem to find anything so it uses the value as is. Even so, it still can't find the class even if you set it directly. So there's a second mystery here.
I suppose I will have to go through Rexster until this is fixed.

At this time titan-node supports Titan 0.4.1 java jar files.
You can upgrade it by replacing new Titan jar files.
Then you can use the code bellow to connect to Titan
var Titan = require('titan-node');
var gremlin = new Titan.Gremlin({ loglevel: 'OFF' });
var BaseConfiguration = gremlin.java.import('org.apache.commons.configuration.BaseConfiguration');
var _confObj={'backend':'cassandra','hostname':'127.0.0.1'};
var TitanFactory = gremlin.java.import('com.thinkaurelius.titan.core.TitanFactory');
conf = new BaseConfiguration();
conf.setPropertySync("storage.backend",_confObj.backend);
conf.setPropertySync("storage.hostname",_confObj.hostname);
var graph = TitanFactory.openSync(conf);
var g = gremlin.wrap(graph);
g.addVertex(null, function (err, saturn) {
console.log('added');
g.commit(function() {
console.log('commited');
});
});

Related

How to get JanusGraphManagement from Java

I can't understand how to get a JanusGraphManagement instance from a graph created with the ConfiguredGraphFactory.
I tried doing something like this:
JanusGraphFactory.Builder config = JanusGraphFactory.build();
config.set("storage.hostname", storageHostname);
config.set("storage.port", storagePort);
config.set("storage.backend", STORAGE_BACKEND);
config.set("index.search.backend", SEARCH_BACKEND);
config.set("index.search.hostname", indexHostname);
config.set("index.search.port", indexPort);
config.set("graph.graphname", graphName);
JanusGraph graph = config.open();
JanusGraphManagement mgmt = graph.openManagement();
But it generates the following exception:
java.lang.NullPointerException: Gremlin Server must be configured to use the JanusGraphManager.
The gremlin-server is ruinning with the following configuration:
host: 0.0.0.0
port: 8182
scriptEvaluationTimeout: 180000
# channelizer: org.apache.tinkerpop.gremlin.server.channel.WebSocketChannelizer
channelizer: org.janusgraph.channelizers.JanusGraphWebSocketChannelizer
graphManager: org.janusgraph.graphdb.management.JanusGraphManager
graphs: {
#graph: conf/gremlin-server/janusgraph-cql-es-server.properties,
ConfigurationManagementGraph: conf/gremlin-server/janusgraph-cql-es-server-configured.properties
}
.....
And the JanusGraph's one is this:
gremlin.graph=org.janusgraph.core.ConfiguredGraphFactory
graph.graphname=ConfigurationManagementGraph
storage.backend=cql
storage.hostname=127.0.0.1
storage.cql.keyspace=janusgraph
cache.db-cache = true
cache.db-cache-time = 180000
cache.db-cache-size = 0.25
index.search.backend=elasticsearch
index.search.hostname=127.0.0.1
index.search.elasticsearch.client-only=true
What I'd like to do is to define the graph schema directly from Java code, that's why I need to the a managment instance and a traversal source is not enough
They really don't seem to want you to do this from Java. Check my initial commit to an example repo I built.
The general deal is that there is a bunch of internal magic happening. You need to make a new embedded instance of the ConfigurationManagementGraph and a few other things. The steps to get ConfiguredGraphFactory up and running are:
JanusGraphManager(Settings())
// the configuration file you used for your ConfigurationManagementGraph in your `janusgrpah-server.yaml` file
val mgrConfFile = File("conf/janusgraph-cql-configurationgraph.properties")
// load the configuration
val base = CommonsConfiguration(ConfigurationUtil.loadPropertiesConfig(mgrConfFile))
// modify a fe wthings specific to the ConfigurationManagementGraph
base.set("graph.graphname", "name-of-this-graph-instance")
base.set("graph.unique-instance-id", "some-super-unique-id")
base.set("storage.lock.local-mediator-group", "tmp")
// duplicate the config for some reason?
val local = ModifiableConfiguration(GraphDatabaseConfiguration.ROOT_NS, base, BasicConfiguration.Restriction.NONE)
// build another type of configuration?
val config = GraphDatabaseConfiguration(base, local, instanceId, local)
// create the new ConfigurationManagementGraph instance
return ConfigurationManagementGraph(StandardJanusGraph(config))
Don't forget that you will still need to create a template configuration first.
Now, you can use the singleton ConfiguredGraphFactory anywhere in your application, just like the docs say.
val myGraph = ConfiguredGraphFactory.open("myGraph")
Keep in mind that you may not need to do this. The Client.submit() function comes in handy for most things. For example:
// connect to the gremlin server
val cluster = Cluster.build("localhost").create()
val client = cluster.connect<Client.ClusteredClient>()
// example: get a list of existing graph names
val existingGraphs = client.submit("ConfiguredGraphFactory.getGraphNames()").all().get()
// check if a graph exists
val exists = existingGraphs.any { it.string == "myGraph" }
// create a new graph with the existing template
// (note: this *cannot* be cast to a JanusGraph, even though that would make this really useful)
val myGraph: TinkerGraph = client.submit("ConfiguredGraphFactory.getGraphNames()").all().get().first().get(TinkerGraph::class.java)
EDIT:
As #FlorianHockmann pointed out on the JanusGraph discord server, it's preferable to not use these objects directly from your Java. Instead, it's better to use a Client.SessionedClient when you connect, like so
val cluster = Cluster.build("localhost").create()
val session = cluster.connect<Client.SessionedClient>()
Since you've established a session, you can now save and re-use variables on the server. As Florian put it,
client.submit("mgmt = ConfiguredGraphFactory.open('myGraph').openManagement()").all().get()
// afterwards you can use it:
client.submit("// do stuff with mgmt").all().get()
Just don't forget to call session.close() when you're done!
Check out this gist I made for an example

Accessing MySQL through node-java

So, I have a node.js project that I am working on for a class. One of the features our group is trying to build, requires calling a Java class method that connects to a MySQL database, does some computation and returns the result to the node server. Here is what we have so far:
Using the node-java library, we are adding the required jars to classpath:
var java = require('java');
var path = require('path');
java.classpath.push(path.join(__dirname, "../java/mysql-connector-java.5.1.38-bin.jar"));
java.classpath.push(path.join(__dirname, "../java/BayesianCurve.jar"));
java.classpath.push(path.join(__dirname, "../java/commons-math3-3.6.jar"));
Then, the class is instantiated and a method is called:
var test = java.newInstanceSync('BayesianCurve');
test.getPrediction(param, function(err, data){
if(err)
{
console.log(err);
return;
}
else
res.send(JSON.stringify(data));
});
So far, so good. The Java class method then has to create a connection to a MySQL database and this is where the problems start:
Class.forName("com.mysql.jdbc.Driver");
//System.setProperty("jdbc.drivers","com.mysql.jdbc.Driver");
//DriverManager.registerDriver(new com.mysql.jdbc.Driver());
System.out.println("Here");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/schema","root","root");
The java code, standalone, is able to connect to the database and execute queries. However, when used through the node-java module, it throws:
ClassNotFoundException: com.mysql.jdbc.Driver
One reason we thought about was that this library is linked dynamically. Somehow, the java environment in node.js is not able to figure this out. However, we are not really sure how to resolve this. Any help in this regard is appreciated.

Use Jackcess from R using rJava

I am not much familiar with Java but I try to accomplish this task in R (my fav)!
There is this Java library called Jackcess. I want to connect to this library and open an MS Access 2003 .mdb file in it. Jackcess cookbook tells me the first step to using this library is this:
Database db = DatabaseBuilder.open(new File("mydb.mdb"));
or as #Gord suggests,
File file = new File("C:/Users/Public/jackcessTest.mdb");
DatabaseBuilder dbbo = new DatabaseBuilder();
dbbo.setFile(file);
Database db = dbbo.open();
but I'm stuck at this very first step.
I have installed Java and rJava and set up everything about directories.
This is my code in R
library(rJava)
.jinit()
.jaddClassPath("java/jackcess-2.1.2.jar") # there I have put the downloaded jar file of Jackcess
# .jaddClassPath("java/commons-logging-1.2.jar") # this is the commons-logging class that Jackcess depends on, commented to replicate problem 2] in my question.
file.name <- "D:/63.mdb" # some data base .mdb file (containing only tables)
file <- .jnew("java/io/File",file.name)
dbbo <- .jnew("com/healthmarketscience/jackcess/DatabaseBuilder")
[Edit: I found out I had two problems, one solved, one still not.]
up to this part everything is ok, but I have some problems from now on:
1] Correctly calling a method from Jackcess without signature mismatch, neither of these work:
dbbo <- .jcall(dbbo,"L<DatabaseBuilder>","setFile",file)
dbbo <- .jcall(dbbo,"Lcom/healthmarketscience/jackcess/DatabaseBuilder","setFile",file)
I get this error:
Error in .jcall(dbbo, "Lcom/healthmarketscience/jackcess/DatabaseBuilder", :
method setFile with signature (Ljava/io/File;)Lcom/healthmarketscience/jackcess/DatabaseBuilder not found
well I found the answer to this step, I just needed a semicolon (;) at the end of class definition string.
dbbo <- .jcall(dbbo,"Lcom/healthmarketscience/jackcess/DatabaseBuilder;","setFile",file)
2] Calling the open method correctly, my first round of try:
db <- .jcall(dbbo,"Lcom/healthmarketscience/jackcess/Database;","open",evalArray = FALSE,evalString = FALSE)
and I get this error:
Error in .jcall(dbbo, "Lcom/healthmarketscience/jackcess/Database;", "open", :
java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
I googled and found out that Jackcess depends on some library called commons-logging, so downloading and adding it to classpath solves THAT problem
3] Calling the open method correctly, my second round of try: with commons-logging in classpath
db <- .jcall(dbbo,"Lcom/healthmarketscience/jackcess/Database;","open",evalArray = FALSE,evalString = FALSE)
this gives me this error:
Error in .jcall(dbbo, "Lcom/healthmarketscience/jackcess/Database;", "open", :
java.lang.NoClassDefFoundError: Could not initialize class com.healthmarketscience.jackcess.impl.DatabaseImpl
Any Ideas for this error?
[NOTE]: some answers were suggested before my edits, so they may seem irrelevant now, but I have used them in the steps I explained above.
The following code shows an alternate approach in Java using the .setFile and .open methods of a "real" DatabaseBuilder object:
File file = new File("C:/Users/Public/jackcessTest.mdb");
DatabaseBuilder dbbo = new DatabaseBuilder();
dbbo.setFile(file);
Database db = dbbo.open();
Try something similar in rJava and see if it works for you.
Edit re: updated question
You mentioned that you added Apache commons-logging to your CLASSPATH, but Jackcess also relies on Apache commons-lang v2.x (not v3.x), so try downloading that and including it in your CLASSPATH as well.
3 suggestions:
Include commons-lang-2.0.jar in your classPath, similarly to
rJava::.jaddClassPath("commons-lang-2.0.jar")
The easy way is to try calling with J() like so:
dbb <- rJava::.jnew("com/healthmarketscience/jackcess/DatabaseBuilder")
dbjfile <- rJava::.jnew('java/io/File', "D:/63.mdb")
dbop <- rJava::J(dbb, "open", dbjfile)
For what it's worth, if you really want to do it the low-level way, this is one way to try:
dbop <- .jcall(
"RJavaTools"
, "Ljava/lang/Object;"
, "invokeMethod"
, .jcall(dbb, "Ljava/lang/Class;", "getClass")
, .jcast(dbb, "java/lang/Object")
, .jnew("java/lang/String", "open")
, .jarray(list(dbjfile), "java/lang/Object", dispatch = FALSE)
, .jarray(rJava:::._java_class_list(list(dbjfile)), "java/lang/Class", dispatch = FALSE)
, use.true.class = TRUE
, evalString = TRUE
, evalArray = FALSE
)

IndicesExistsResponse.isExists() not working for embedded ElasticSearch instance

I am using the following java code to create instance of ElasticSearch instance and create a index called "testindex".
Node node = NodeBuilder.nodeBuilder().settings(ImmutableSettings.settingsBuilder()
.put("path.data", "/etc/elasticsearch")
.put("cluster.name", "testcluster"))
.node();
Client client = node.client();
IndicesAdminClient indices = client.admin().indices();
IndicesExistsResponse res = indices.prepareExists("testindex").execute().actionGet();
if(!res.isExists()){ //Everytime getting value as false
CreateIndexRequestBuilder createIndexRequestBuilder = indices.prepareCreate("testindex");
createIndexRequestBuilder.execute().actionGet(); // Erring out with IndexAlreadyExistsException
}
Before creating the index I am checking whether index exists or not, I only create the index if it exists.
Second time when I am running the above code, it fails with IndexAlreadyExistsException.
It seems like the IndicesExistsResponse.isExists() is not behaving correctly.
Above code works fine if default elasticsearch.yml file is present in the classpath. IndicesExistResponse.isExists() returns true if elasticsearch.yml is in the classpath.
Any workaround to resolve the issue ?
Please have a look at:
if(res.isExists()){
...
}
You want to create the index if it exists.

Creating and retrieving JIRA remote issue links

I am trying to write a transition post function for JIRA v5.x. It should check if there is already a Confluence page linked with the issue, and create and link the page if not.
I am developing this using the a groovy script and the scriptrunner plugin which can access the JAVA API.
While it was fairly easy to create the confluence page, I am struggling with the remote issue links.
How can I create a new remote issue link?
How can I determine if a link already exists for an issue?
This is how I try to create the link:
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.bc.issue.link.RemoteIssueLinkService
import com.atlassian.jira.issue.link.RemoteIssueLinkBuilder
//I use a wrapper class for the moment so I can run via scriptrunner and debug it in IDEA
class myWrapper {
def doStuff() {
//get the issue, this would already be available in an post action
def issueService = ComponentManager.getInstance().getIssueService();
def authContext = ComponentManager.getInstance().getJiraAuthenticationContext()
def issueResult = issueService.getIssue(authContext.getUser(), "DEV-1");
def issue = issueResult.getIssue()
//build link
def linkBuilder = new RemoteIssueLinkBuilder()
linkBuilder.issueId(issue.id)
linkBuilder.applicationName("myconluence")
linkBuilder.applicationType("com.atlassian.confluence")
linkBuilder.relationship("Wiki Page")
linkBuilder.title("testpage")
linkBuilder.url("http://localhost:8090/display/LIN/testpage")
linkBuilder.build()
def validationResult = RemoteIssueLinkService.validateCreate(authContext.getUser(), linkBuilder)
}
}
(new myWrapper()).doStuff()
When I run the code I get the following exception:
javax.script.ScriptException: groovy.lang.MissingMethodException: No signature of method: static com.atlassian.jira.bc.issue.link.RemoteIssueLinkService.validateCreate() is applicable for argument types: (com.atlassian.crowd.embedded.ofbiz.OfBizUser, com.atlassian.jira.issue.link.RemoteIssueLinkBuilder) values: [admin:1, com.atlassian.jira.issue.link.RemoteIssueLinkBuilder#180ca9]
For me it looks like I do not get the RemoteIssueLinkService correctly,but I do not know what I have to do to fix that.
I asked the same question in the atlassian forum . Here is the working answer that I received from Jamie Echlin for future reference
It's not a static method, so you need to get an instance of the class first:
def remoteIssueLinkService = ComponentManager.getComponentInstanceOfType(RemoteIssueLinkService.class)
remoteIssueLinkService.validateCreate(...)

Categories