Why does DriverManager.getConnection() lookup fail in GroovyConsole? - mysql

The following Groovy script works correctly from the command line. (I successfully get a Connection.)
// ---- jdbc_test.groovy
import java.sql.*
Class.forName("com.mysql.jdbc.Driver")
def con = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/test",
"root",
"password")
println con
> groovy -cp lib\mysql-connector-java-5.1.25-bin.jar script\jdbc_test.groovy
com.mysql.jdbc.JDBC4Connection#6025e1b6
But if the same script is loaded into GroovyConsole (2.4.3) and run - after adding the mysql-connector-java-5.1.25-bin.jar using 'Script' | 'Add Jar(s) to ClassPath' - it fails:
java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost:3306/test
at java_sql_DriverManager$getConnection.call(Unknown Source)
at jdbc_test.run(jdbc_test.groovy:3)
Every other package or class I have added to the classpath in GroovyConsole and experimented with has worked. Is there some unexpected interaction of Groovy's class loading and the way DriverManager works?
Is there a way around this? I'm trying to use the GroovyConsole to interactively test out some JDBC code (a library of functions, each of which takes a Connection as its first argument).
UPDATE: The Class.forName() part appears to be working fine. If I 'Script' | 'Clear Script Context' and rerun the script in GroovyConsole, I instead get:
java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
If I add mysql-connector-java-5.1.25-bin.jar back in, I go back to getting:
java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost:3306/test

Solution: The driver has to be on the classpath.
Reason:
If you look into the DriverManager class you find code like this: Class.forName(driver.getClass().getName(), true, classLoader);. This is to check if the driver is accessible from your classloader context. And that context is determined by going back to the class that is calling he DriverManager. This code is written for Java, thus assumes a certain amount of frames on the call stack to go back. Since Groovy does not do direct calls (unless you use #CompileStatic) this number is wrong and leads usually to a Groovy core class to be selected, resulting in Groovy main loader to be selected.... in the past this was often even the JDK system classloader because of reflection. So even though the driver is loaded and registered, it is not accessible to you.
Note: with jdbc4 the driver should register itself, just by being on the classpath

Related

How can I externalize ISchedulerExecutorService to run tasks in an external hazelcast cluster(Hazecast 5.2) without using UserCodeDeployment?

I am working on externalizing our IScheduledExecutorService so I can run tasks externally on a external cluster. I am able to write a test and get the Runnable to actually run ONLY if I turn on UserCode deployment. If I want to change this task at all and run the tests again I get the below in my external cluster member's logs..
java.lang.IllegalStateException: Class com.mycompany.task.ScheduledTask is already in local cache and has conflicting byte code representation
I want to be able to change the task if I could and redeploy to Hazelcast to just handle it. I do this kind of thing with our external maps now. It can handle different versions of our objects using compact serialization.
Am I stuck using user code deployment for these functional objects? If I need to make a change to it I need to change the class name and redeploy to production. I'm hoping to get this task right the first time and not have to ever do that but I have a way of handling it if I do.
The cluster is already running in production and I'll have to add the following to each member
HZ_USERCODEDEPLOYMENT_ENABLED=true
and the appropriate client code(listed below) to enable this.
What I've done...
Added the following to my local docker file
HZ_USERCODEDEPLOYMENT_ENABLED=true
and also in the code that creates a hazelcast client connecting to my external cluster with
ClientConfig clientConfig = new ClientConfig(); ClientUserCodeDeploymentConfig clientUserCodeDeploymentConfig = new ClientUserCodeDeploymentConfig(); clientUserCodeDeploymentConfig.addClass("com.mycompany.task.ScheduledTask"); clientUserCodeDeploymentConfig.setEnabled(true); clientConfig.setUserCodeDeploymentConfig(clientUserCodeDeploymentConfig);
However, if I remove those two pieces I get the following Exception with a failing test. It doesn't know about my class at all.
com.hazelcast.nio.serialization.HazelcastSerializationException: java.lang.ClassNotFoundException: com.mycompany.task.ScheduledTask
Side Note:
We are using compact serialization for several maps already and when I try to configure this Runnable task via compact serialization I get the below error. I don't think that's the right approach either.
[Scheduler: myScheduledExecutorService][Partition: 121][Task: 7afe68d5-3185-475f-b375-5a82a7088de3] Exception occurred during run
java.lang.ClassCastException: class com.hazelcast.internal.serialization.impl.compact.DeserializedGenericRecord cannot be cast to class java.lang.Runnable (com.hazelcast.internal.serialization.impl.compact.DeserializedGenericRecord is in unnamed module of loader 'app'; java.lang.Runnable is in module java.base of loader 'bootstrap')
at com.hazelcast.scheduledexecutor.impl.ScheduledRunnableAdapter.call(ScheduledRunnableAdapter.java:49) ~[hazelcast-5.2.0.jar:5.2.0]
at com.hazelcast.scheduledexecutor.impl.TaskRunner.call(TaskRunner.java:78) ~[hazelcast-5.2.0.jar:5.2.0]
at com.hazelcast.internal.util.executor.CompletableFutureTask.run(CompletableFutureTask.java:64) ~[hazelcast-5.2.0.jar:5.2.0]

Attribute is required but not set (Unable to create snapshot class for interface)

My Liferay 7 server was using SomeModule happily, until I deployed a new version of SomeModule which has an additional required field favoriteColor.
Now whenever I try to load the portlet Liferay says:
java.lang.RuntimeException: Unable to create snapshot class for interface some.SomeModuleConfiguration
at com.liferay.portal.configuration.metatype.bnd.util.ConfigurableUtil._createConfigurableSnapshot(ConfigurableUtil.java:77)
at com.liferay.portal.configuration.metatype.bnd.util.ConfigurableUtil.createConfigurable(ConfigurableUtil.java:51)
at some.SomeModule.activate(SomeModule.java:50)
...
aused by: java.lang.IllegalStateException: Attribute is required but not set favoriteColor
at aQute.bnd.annotation.metatype.Configurable$ConfigurableHandler.invoke(Configurable.java:75)
at com.sun.proxy.$Proxy1220.favoriteColor(Unknown Source)
at some.SomeModuleConfigurationSnapshot407.<init>(Unknown Source)
The configuration UI for SomeModule does not show anything about favoriteColor.
How to fix that, for instance by setting favoriteColor to its default value?
An alternative path would be using a OSGi configuration file to set defaults and missing values. You can use those files as you do for those modules that come with liferay; e.g., elasticsearch config. (check your osgi/configs directory)
If you are lucky enough to have the source code of the module, you can solve this problem like this:
Temporarily make the new field optional, but replacing required = true to required = false in SomeModuleConfiguration.java.
Deploy the module.
Load the configuration page, save.
Restore to required = true.
Deploy again.
Alternative answers welcome!

Weka Find Database Util Properties But Throwing Driver Not Found

I build a simple weka application using Weka 3.7.13 dev version using MAVEN. I have initialise the pom.xml function to get weka library from the repository.
i want to run a simple clustering algorithm using weka, and connecting it to MySQL database. As per documentation, the weka need to have a DatabaseUtil.props file which contains it's jdbc driver. I have setup that.
This is my project structure:
I can retrieve the DatabaseUtils.props using my code below. But somehow the weka itself cannot recognise the jdbc:Url and driver name which i already configure inside.
DatabaseUtil.props file:
# JDBC driver (comma-separated list)
jdbcDriver=com.mysql.jdbc.Driver
# database URL
jdbcURL=jdbc:mysql://127.0.0.1:3306/datamining
Java code which i trigger the Weka module:
public void dm(){
int cluster = 4;
InstanceQuery clusterQuery = null;
try{
//file reader of database utilities properties
ClassLoader classLoader = getClass().getClassLoader();
File fileProps = new File(classLoader.getResource("DatabaseUtils.props").getFile());
//setup the data preparation functionality then connect to database
clusterQuery = new InstanceQuery();
clusterQuery.setUsername("test");
clusterQuery.setPassword("test");
clusterQuery.setQuery("SELECT * FROM TEMP_KMEANS");
clusterQuery.setCustomPropsFile(fileProps);
But when executed the function returning error: java.sql.SQLException: No suitable driver found for jdbc:idb=experiments.prp
It seems that the DatabaseUtils.props file cannot override the default driver value jdbc:idb=experiments.prp
Any ideas why this is throwing?
Any feedback and answer much appreciated.
I created a DatabaseUtils.props file in the src / main / resources folder and wrote the following code. It worked for me, I'm using weka 3.8.0.
File file = new File(getClass().getClassLoader().getResource("DatabaseUtils.props").toURI());
InstanceQuery query = new InstanceQuery();
query.setCustomPropsFile(file);
query.setUsername(MYSQL_USER);
query.setPassword(MYSQL_PASSWORD);
query.setQuery("select * from Action");
instances = query.retrieveInstances();
System.out.println(instances.toString());
The documentation says "These may be changed by creating a java properties file called DatabaseUtils.props in user.home or the current directory". Your properties file does not match those requirements (a properties file in a jar is not on the filesystem). See also Chapter 14 of the Weka manual.
An alternative solution is to set the URL in code using setDatabaseURL. As long as the JDBC driver is on the classpath this should work.

Using JUnit in Jython - NameError for assertTrue

Environment Details
Mac OS X 10.9
Oracle JDK 1.7.0_55 64-bit
jython-standalone-2.5.3.jar
junit-4.11
What I have done so far
I have added the junit jar to /Library/Java/Extensions.
I invoked Jython as follows java -jar jython-standalone-2.5.3.jar
In the Jython interpreter, I imported the following import org.junit.Assert, and this import was successful.
Problem
When I tried to use assertTrue, I got a NameError in the interpreter. Why is this so?
I understand that assertTrue is a static method. Not sure what implication this has when I try to use it in Jython.
Additional Context
I am using XMLUnit in Jython. Was able to successfully import the Diff class from org.custommonkey.xmlunit in Jython. Also able to use the methods in this class, and call them on a Diff object. The result of this method call is what I am trying to pass to assertTrue, when it throws the error.
from org.custommonkey.xmlunit import Diff
import org.junit.Assert
xml1 = ...some XML string...
xml2 = ...some XML string...
myDiff = Diff(xml1, xml2)
assertTrue(myDiff.similar())
Hope this additional information is useful in identifying a solution to this problem.
Latest Status
I narrowed it down to setting this property python.security.respectJavaAccessibility = false, since the Assert() constructor is protected.
Still trying to get it to work. Any help is greatly appreciated.
Figured it out.
In addition to junit.jar file, the hamcrest-core.jar file also needed to be copied to /Library/Java/Extensions.
Then I got rid of the jython.jar file, and instead installed it using the jython installer.
After the installation was completed, I updated the registry file in the installation folder, specifically setting this property python.security.respectJavaAccessibility = false.
Now I am able to see the assertTrue method, and no longer getting a NameError.

Connection with mysql with netbeans for jsp [duplicate]

This question already has answers here:
The infamous java.sql.SQLException: No suitable driver found
(21 answers)
How should I connect to JDBC database / datasource in a servlet based application?
(2 answers)
Closed 2 years ago.
I am using NetBeans 7.0.1 IDE for JSP/servlet
I am trying to make a database connection for my project. Already downloaded the jar file 'mysql-connector-java-5.1.24-bin.jar' pasted it to jdk's jre/lib dir, also added it to my netbean projects libraries dir.
then I created a servlet and wrote the following code:
import java.sql.*;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class tstJDBC extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try{
String dbURL = "jdbc:mysql://localhost:3306/murach";
String username="root";
String password="1234";
Connection con2 = DriverManager.getConnection(dbURL, username, password);
String query = "insert into tblUser1(firstname) values('shaon')";
Statement statmnt = con2.createStatement();
statmnt.executeUpdate(query);
}
catch(SQLException e)
{
e.printStackTrace();
}
}
}
But it can establish the connection. From the line Connection con2, its directly going to catch() block ; without executing the query.
Try loading the driver prior to using the DriverManager class.
try{
String dbURL = "jdbc:mysql://localhost:3306/murach";
String username="root";
String password="1234";
Class.forName("com.mysql.jdbc.Driver");//load driver
Connection con2 = DriverManager.getConnection(dbURL, username, password);
String query = "insert into tblUser1(firstname) values('shaon')";
Statement statmnt = con2.createStatement();
statmnt.executeUpdate(query);
}
From O'Reilly:
Before you can use a driver, it must be registered with the JDBC
DriverManager. This is typically done by loading the driver class
using the Class.forName( ) method:
This is required since you have placed the library within the JDK/lib folder which I'm assuming is loaded using a different ClassLoader than the one used by your application. Since different class loaders were used the automatic registration that takes place by JDBC 4.0+ drivers will not take effect. You could try to place the driver jar file within the lib of your application server, which should use the same ClassLoader of your application. See: When is Class.forName needed when connecting to a database via JDBC in a web app?
Regarding Automatic Registration
In JDBC 4.0, we no longer need to explicitly load JDBC drivers using
Class.forName(). When the method getConnection is called, the
DriverManager will attempt to locate a suitable driver from among the
JDBC drivers that were loaded at initialization and those loaded
explicitly using the same class loader as the current application.
The DriverManager methods getConnection and getDrivers have been
enhanced to support the Java SE Service Provider mechanism (SPM).
According to SPM, a service is defined as a well-known set of
interfaces and abstract classes, and a service provider is a specific
implementation of a service. It also specifies that the service
provider configuration files are stored in the META-INF/services
directory. JDBC 4.0 drivers must include the file
META-INF/services/java.sql.Driver. This file contains the name of the
JDBC driver's implementation of java.sql.Driver. For example, to load
the JDBC driver to connect to a Apache Derby database, the
META-INF/services/java.sql.Driver file would contain the following
entry:
org.apache.derby.jdbc.EmbeddedDriver
Let's take a quick look at how we can use this new feature to load a
JDBC driver manager. The following listing shows the sample code that
we typically use to load the JDBC driver. Let's assume that we need to
connect to an Apache Derby database, since we will be using this in
the sample application explained later in the article:
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
Connection conn =
DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPassword);
But in JDBC 4.0, we don't need the Class.forName() line. We can simply
call getConnection() to get the database connection.
Source
Regarding Service Loaders
For the purpose of loading, a service is represented by a single
type, that is, a single interface or abstract class. (A concrete class
can be used, but this is not recommended.) A provider of a given
service contains one or more concrete classes that extend this service
type with data and code specific to the provider. The provider class
is typically not the entire provider itself but rather a proxy which
contains enough information to decide whether the provider is able to
satisfy a particular request together with code that can create the
actual provider on demand. The details of provider classes tend to be
highly service-specific; no single class or interface could possibly
unify them, so no such type is defined here. The only requirement
enforced by this facility is that provider classes must have a
zero-argument constructor so that they can be instantiated during
loading.
A service provider is identified by placing a provider-configuration
file in the resource directory META-INF/services. The file's name is
the fully-qualified binary name of the service's type. The file
contains a list of fully-qualified binary names of concrete provider
classes, one per line. Space and tab characters surrounding each name,
as well as blank lines, are ignored. The comment character is '#'
('\u0023', NUMBER SIGN); on each line all characters following the
first comment character are ignored. The file must be encoded in
UTF-8.
If a particular concrete provider class is named in more than one
configuration file, or is named in the same configuration file more
than once, then the duplicates are ignored. The configuration file
naming a particular provider need not be in the same jar file or other
distribution unit as the provider itself. The provider must be
accessible from the same class loader that was initially queried to
locate the configuration file; note that this is not necessarily the
class loader from which the file was actually loaded.
Source
just Keep the "mysql-connector-java" in "C:\Program Files\Java\jdk1.7.0_25\jre\lib\ext"
the "jdk1.7.0_25" is my version of jdk may be you have different version but will must have the sub folders "\jre\lib\ext" inside that.