I'm trying to do some JDBC access from JavaScript using the Rhino included in Java 6. But I cannot make the DriverManager find the Driver I want to use.
These two examples should be equivalent:
Java:
public class DbTest {
public static void main(String[] argv) {
java.sql.Connection c = null;
try {
java.lang.Class.forName("net.sourceforge.jtds.jdbc.Driver");
c = java.sql.DriverManager.getConnection(
"jdbc:jtds:sqlserver://myserver/mydb", "user", "password");
}
catch (Exception e) {
c = null;
System.out.println(e);
};
if(c != null) {
System.out.println("yay, got c!");
try {
c.close();
}
catch(Exception e) {}
} else {
System.out.println("awww.");
}
}
}
JavaScript:
importPackage(Packages.net.sourceforge.jtds.jdbc);
java.lang.Class.forName('net.sourceforge.jtds.jdbc.Driver');
var c = null;
try {
c = java.sql.DriverManager.getConnection(
'jdbc:jtds:sqlserver://myserver/mydb', 'user', 'password');
}
catch (e) {
c = null;
println(e);
};
if(c) {
println('yay, got c!');
c.close();
} else {
println('awww.');
}
... but when I run them I get this behaviour:
Java:
> java -cp .;jtds-1.2.5.jar DbTest
java.sql.SQLException: Unknown server host name 'myserver'.
awww.
That's great, it managed to load the driver and tried to resolve the server.
JavaScript:
> jrunscript -cp .;jtds-1.2.5.jar dbtest.js
script error in file dbtest.js :
sun.org.mozilla.javascript.internal.WrappedException:
Wrapped java.lang.ClassNotFoundException:
net.sourceforge.jtds.jdbc.Driver (dbtest.js#2) in dbtest.js at line number 2
Why doesn't it find the class? I have tried with and without importPackage() and importClass(), with and without the Packages prefix. If I comment out forName, then DriverManager doesn't find a suitable driver.
According to an IBM DeveloperWorks forum post, "the jrunscript -classpath value is used by a separate "scripting" classloader that parallels the usual application classloader and that is used to resolve classes that have been mentioned in importClass() and importPackage()".
And according to this SO answer, "... DriverManager performs "tasks using the immediate caller's class loader instance" ".
So, unless you put the driver jar into the bootclasspath or find a way to modify how jrunscript (and Ant <script />) set the system classloader of the script environment, the only way to get this to work seems to be to skip DriverManager entirely:
var c = null;
try {
var p = new java.util.Properties();
p.setProperty('user', 'user');
p.setProperty('password', 'password');
c = (new net.sourceforge.jtds.jdbc.Driver()).connect(
'jdbc:jtds:sqlserver://myserver/mydb', p);
}
catch (e) {
c = null;
println(e);
};
if(c) {
println('yay, got c!');
c.close();
} else {
println('awww.');
}
It removes one layer of indirection, which may or may not be ones cup of tea, but it works (with real server/user/passwd inserted):
$ jrunscript -cp jtds-1.2.5.jar dbtest_realparams.js
yay, got c!
Related
I'm asking because ALL examples I find in Google, are the same from the Fitnesse tutorial: a very simple query to a list or array in memory, NOT A REAL Database.
Yes, Fixtures never have to deal with that, but how am I supposed to test my fixtures if I can't even make the connection to the DB in a simulation of an "API"?
What I'm trying to simulate is the call from a FitNesse Fixture to query in Java into a PostgreSQL database/table. In this simple example I'm trying to obtain, at least one column from one row, in one table. When I execute the code, it runs perfectly by it's own. The problem is when trying to execute from Fitnesse through the fixture. It always fails with a ClassNotFoundException, when calling the JDBC driver. This doesn't happen by running the code by it's own.
Here is the code that does the query:
package queriespackage;
import java.sql.*;
public class testQuery01 {
public static Connection openDBConnection(){
Connection connectionString = null;
try {
String dbhost = "SOMEURL";//Redacted
String port = "SOMEPORT";//Redacted
String dbname = "THEDBNAME";//Redacted
String username = "SOMEUSER";//Redacted
String password = "SOMEPASSWORD";//Redacted
String driverJDBC = "org.postgresql.Driver";
Class.forName(driverJDBC);
connectionString = DriverManager.getConnection("jdbc:postgresql://" + dbhost + ":" + port + "/" + dbname,username,password);
connectionString.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace(System.err);
System.exit(0);
} catch (Exception e) {
System.err.println( e.getClass().getName()+": "+ e.getMessage() );
System.exit(0);
};
return connectionString;
};
public static ResultSet executeQuery(Connection connectionString, int intAccountId) throws SQLException{
Statement querySession = connectionString.createStatement();
//The query string
String queryString = "SELECT DISTINCT "
+ "account_search.account_id,"
+ "account_search.account_name"
+ " FROM account_search "
+ " WHERE"
+ " account_search.account_id = "+ intAccountId
+ "LIMIT 1";
ResultSet queryResult = querySession.executeQuery(queryString);
return queryResult;
};
public static String processQueryResult(ResultSet queryResult) throws SQLException{
String strQueryValueReturned = null;
while (queryResult.next()) {
strQueryValueReturned = queryResult.getString("account_name");
};
return strQueryValueReturned;
};
public static boolean closeDBConnection(Connection connectionString){
try {
if(connectionString!=null){
connectionString.close();
}
} catch (SQLException e) {
System.err.println( e.getClass().getName()+": "+ e.getMessage() );
System.exit(0);
};
return true;
};
public static String testQuery(int intAccountId) throws SQLException, ClassNotFoundException{
boolean bolConnectionStatus = false;
String strValueReturned = null;
Connection connectionString = openDBConnection();
if(connectionString != null){
ResultSet qryQueryResult = executeQuery(connectionString, intAccountId);
strValueReturned = processQueryResult(qryQueryResult);
bolConnectionStatus = closeDBConnection(connectionString);
if(!bolConnectionStatus){
System.exit(0);
}
}else{
System.exit(0);
};
return strValueReturned;
};
};
If I add a Main method to that code, passing it the argument value for "intAccountId", it successfully returns the name of the account "account_name", just as expected.
Now here's the Fixture that should be called by the FitNesse test:
package fixturespackage;
import java.sql.SQLException;
import queriespackage.testQuery01;
public class testFixture01{
private int Int_AccountId;
//Fixture Constructor (setter)
public testFixture01(int Int_AccountId){
this.Int_AccountId = Int_AccountId;
};
public String query() throws SQLException, ClassNotFoundException{
return testQuery01.testQuery(Int_AccountId);
};
};
Just as the FitNesse guide says, there must be a "query" method, that does the actual call to the interface in the DB. I had to add a constructor instead of the "setter", because FitNesse actually demands it: "Could not invoke constructor for fixturepackage.testFixture01"
Here's the FitNesse page:
!***> System Variables
!define TEST_SYSTEM {slim}
!path C:\FitnessTest\bin
*!
|Query: fixturespackage.testFixture01|21 |
|Str_AccountName |
|SomeName |
Here's a Screenshot of my BuildPath, so you can see I have the JDBC Library for Java 8, JDK 1.8, JRE 1.8... and the "org.postgresql.Driver.class" is included in the project.
This is the error I receive, when running from FitNesse:
This is the error I get, when debugging the line where FitNesse failed by using Inspect tool:
... and YES, I also tried by hard coding the name of the JDBC:
I have searched a lot for a REAL LIFE example, both here, the FitNesse Guide and Google.
The FitNesse Guide might be extensive, but let's be sincere, it's full of "dirty word here", unrealistic and incomplete examples and missing a lot of information.
So, asking again, has anyone done a REAL LIFE test making queries, using FitNesse, that could help me find out what am I doing wrong?
I have to admit I've only done limited database tests with FitNesse, but I have used them (to query DB2).
I did not use query tables (or wrote my own fixtures to query), but instead used jdbcslim in combination with script tables and scenario's.
That fact that the driver class cannot be found suggests that although the jar is present on the classpath in your IDE it is not available when FitNesse is running your fixture code.
I notice you specify the classpath as a single directory in the wiki. In Java that means that all class files should be in that directory (as .class files, in the right subdirectory for their defined package). It will not pick up any jars (or zips) in that directory. Did you unpack your database driver's jar to that directory? If not, you need to add a !path line pointing to the jar (so the entire path including the filename) with the database driver.
Now listing every jar you need can quickly become cumbersome, so you can also use wildcards. I tend to copy all the jars I need to a single directory, that also contains my fixture .class files, and add a single !path line loading all jars in that directory.
So if you also copied your database driver to the directory in you question you could ensure it, and your own fixture, to be available via
!path C:\FitnessTest\bin
!path C:\FitnessTest\bin\*.jar
I've a strange problem, I cannot compile following code (with Java 8, with Java 6 I've no problems!).
I got following compile-time errors:
Compile Error 1:
error: cannot access CPCallbackClassLoaderIf
com.sun.javaws.jnl.JARDesc[] descs = jnlpcl.getLaunchDesc().getResources().getEagerOrAllJarDescs(true);
class file for com.sun.deploy.security.CPCallbackClassLoaderIf not found
and
Compile Error 2:
error: cannot access XMLable
com.sun.javaws.jnl.JARDesc[] descs = jnlpcl.getLaunchDesc().getResources().getEagerOrAllJarDescs(true);
class file for com.sun.deploy.xml.XMLable not found
NetBeans IDE shows no errors in this code!.
public static List<String> test() {
try {
List<String> ret = new ArrayList<String>();
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if (cl instanceof com.sun.jnlp.JNLPClassLoader) {
com.sun.jnlp.JNLPClassLoader jnlpcl = (com.sun.jnlp.JNLPClassLoader)cl;
/*COMPILE ERROR1*/ com.sun.javaws.jnl.JARDesc[] descs = jnlpcl.getLaunchDesc().getResources().getEagerOrAllJarDescs(true);
for (com.sun.javaws.jnl.JARDesc d : descs)
{
/*COMPILE ERROR2*/ JarFile jf = jnlpcl.getJarFile(d.getLocation());
ret.add(new File(jf.getName()).getAbsolutePath());
}
}
return ret;
} catch (Exception ex) {
//ignore
}
return null;
}
I checked deploy.jar and indeed, this class does not exists anymore in Java 8 (but in Java 6).
Why does this error happens and how can I get rid of this error, when using this code and Java 8?
I'm new to Java and is trying to learn how to determine the MIME type of a file. I'm using Mac OS. Below is the code I came up with. However, when I run the code, the IDE output error:
'/Users/justin/Desktop/Codes Netbean/JavaRandom/xanadu.txt' has an unknown filetype.
Why is this happening? The file does exist. Am I doing something wrong?
public class DeterminingMIMEType {
public static void main(String[] args) {
Path filename = Paths.get("/Users/justin/Desktop/Codes Netbean/JavaRandom/xanadu.txt");
try {
String type = Files.probeContentType(filename);
if (type == null) {
System.err.format("'%s' has an" + " unknown filetype.%n", filename);
} else if (!type.equals("text/plain")) {
System.err.format("'%s' is not" + " a plain text file.%n", filename);
}
} catch (IOException x) {
System.err.println(x);
}
}
}
The documentation for Files reveals that a FileTypeDetector is loaded by ServiceLoader. A wee bit of googling leads to:
http://blog.byjean.eu/java/2013/08/22/making-jdk7-nio-filetypedetection-work-on-mac-osx.html
which says that this is a problem with the default FileTypeDetector provided by the Oracle Java7 jvm for Mac OS.
The link also has a way of providing your own FileTypeDetector, though upgrading to Java 8 (maybe?) also will fix the problem.
I have build an application connecting R and java using the Rserve package.
In that, i am getting the error as "evaluation successful but object is too big to transport". i have tried increasing the send buffer size value in Rconnection class also. but that doesn't seem to work.
The object size which is being transported is 4 MB
here is the code from the R connection file
public void setSendBufferSize(long sbs) throws RserveException {
if (!connected || rt == null) {
throw new RserveException(this, "Not connected");
}
try {
RPacket rp = rt.request(RTalk.CMD_setBufferSize, (int) sbs);
System.out.println("rp is send buffer "+rp);
if (rp != null && rp.isOk()) {
System.out.println("in if " + rp);
return;
}
} catch (Exception e) {
e.printStackTrace();
LogOut.log.error("Exception caught" + e);
}
//throw new RserveException(this,"setSendBufferSize failed",rp);
}
The full java class is available here :Rconnection.java
Instead of RServe, you can use JRI, that is shipped with rJava package.
In my opinion JRI is better than RServe, because instead of creating a separate process it uses native calls to integrate Java and R.
With JRI you don't have to worry about ports, connections, watchdogs, etc... The calls to R are done using an operating system library (libjri).
The methods are pretty similar to RServe, and you can still use REXP objects.
Here is an example:
public void testMeanFunction() {
// just making sure we have the right version of everything
if (!Rengine.versionCheck()) {
System.err.println("** Version mismatch - Java files don't match library version.");
fail(String.format("Invalid versions. Rengine must have the same version of native library. Rengine version: %d. RNI library version: %d", Rengine.getVersion(), Rengine.rniGetVersion()));
}
// Enables debug traces
Rengine.DEBUG = 1;
System.out.println("Creating Rengine (with arguments)");
// 1) we pass the arguments from the command line
// 2) we won't use the main loop at first, we'll start it later
// (that's the "false" as second argument)
// 3) no callback class will be used
engine = REngine.engineForClass("org.rosuda.REngine.JRI.JRIEngine", new String[] { "--no-save" }, null, false);
System.out.println("Rengine created...");
engine.parseAndEval("rVector=c(1,2,3,4,5)");
REXP result = engine.parseAndEval("meanVal=mean(rVector)");
// generic vectors are RVector to accomodate names
assertThat(result.asDouble()).isEqualTo(3.0);
}
I have a demo project that exposes a REST API and calls R functions using this package.
Take a look at: https://github.com/jfcorugedo/RJavaServer
I'm using grph library for a university project (www.i3s.unice.fr/~hogie/grph/)
but i have a problem only on Linux with that library, when i create a new Graph object, i receive the following exception:
Exception in thread "main" java.lang.ExceptionInInitializerError
at org.elendev.wesproject.graph.GraphFactory.main(GraphFactory.java:19)
Caused by: java.lang.NullPointerException
at toools.os.OperatingSystem.getLocalOS(OperatingSystem.java:47)
at grph.Grph.setCompilationDirectory(Grph.java:353)
at grph.Grph.<clinit>(Grph.java:246)
... 1 more
I tried to call directly getLocalOS function, with:
System.out.println(toools.os.OperatingSystem.getLocalOS());
and i receive the same exception. I cannot find information about that library, and the project launched on a macbook works perfectly.
The operating system i'm currently using is gentoo linux 32bit.
And the jdk version is: 1.7.0_65
Any idea of what could be the problem?
Not sure whether this can count as an answer, but it could at least help to solve the issue:
The exception comes from the toools.os.OperatingSystem.getLocalOS method. Although the .JAR file from the website that you mentioned has a whopping 39 megabytes, the source code of this class is not contained in it.
There seems to be no information available about this class at all. Neither Google nor Maven finds anything related to the toools package. One has to assume that it is an abandoned utility class that passed away a long time ago.
However, the method in question can be disassembled to the following code:
public static OperatingSystem getLocalOS()
{
if (localOS == null)
{
if (new RegularFile("/etc/passwd").exists())
{
if (new Directory("/proc").exists())
{
if (new RegularFile("/etc/fedora-release").exists()) {
localOS = new FedoraLinux();
} else if (ExternalProgram.commandIsAvailable("ubuntu-bug")) {
localOS = new UbuntuLinux();
} else {
localOS = new Linux();
}
}
else if (new Directory("/Applications").exists()) {
localOS = new MacOSX();
} else {
localOS = new Unix();
}
}
else if (System.getProperty("os.name").startsWith("Windows")) {
localOS = new Windows();
} else {
localOS = new OperatingSystem();
}
localOS.name = System.getProperty("os.name");
localOS.version = System.getProperty("os.version");
}
return localOS;
}
From this, you can possibly derive the conditions that must be met in order to properly detect your OS as a linux OS. Particularly, when there is a file named /etc/passwd, and a directory /proc, this should be sufficient to identify the OS as a Linux. You may want to give it a try...