How to use a JDBC driver in a Gradle project? - java

I tried to connect with my PostgreSQL database using the following connection string:
"jdbc:postgresql://localhost:5432/test_stock_game"
I got an error:
No suitable driver found for "jdbc:postgresql://localhost:5432/test_stock_game"
I tried both downloading the driver manually (and setting it as a Gradle dependency) and just adding a dependency for Gradle to download.
This is my build.gradle file:
plugins {
id 'java'
}
group 'org.stock_game'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
//implementation 'org.postgresql:postgresql:42.5.2'
implementation files("libs/postgresql-42.5.2")
}
test {
useJUnitPlatform()
}
I tried the two last lines from "dependencies", but got the same error, although I have the driver in Gradle's libs directory (which is in build directory).
Does anyone know what could be the issue here?
This is the code I am using to connect to the database, if that is helpful:
private DBConnection() {
String jdbcConnectionString = "\"jdbc:postgresql://localhost:5432/test_stock_game\"";
String user = "postgres";
String password = "root";
try {
connection = DriverManager.getConnection(jdbcConnectionString, user, password);
} catch (SQLException e) {
System.err.println("Failed to establish database connection");
e.printStackTrace();
}
}

For some reason I constructed the connection string with quotation marks inside, thinking i needed to include them.
It was like this:
"\"jdbc:postgresql://localhost:5432/test_stock_game\""
Changing it to this:
"jdbc:postgresql://localhost:5432/test_stock_game"
made it work.
Thanks Mark Rotteveel, who spotted that it was an issue.

Related

Problem when auto generating gRPC stub files using Gradle

I've been asked to implement some gRPC classes for a college course, and have run into some problems when generating the java classes from one source proto file.
Some background first: it's a fairly basic service, with a simple method that receives an id and returns a phone and an email. This is the proto file (BuscarData means FetchData, sorry for the leftover non translation!):
syntax = 'proto3';
option java_multiple_files=true;
option java_generic_services= true;
package uy.edu.um.sd20;
message DataRequest {
int32 id = 1;
}
message DataResponse {
string phone = 1;
string email = 2;
}
service DataRepo {
rpc BuscarData (DataRequest) returns (DataResponse);
}
The idea I had was to generate the classes with gradle plugins. My build.gradle:
plugins {
id 'java'
id "com.google.protobuf" version '0.8.8'
}
apply plugin: 'java'
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
compile group: 'com.google.protobuf', name: 'protobuf-java', version: '3.11.4'
implementation 'io.grpc:grpc-netty-shaded:1.29.0'
implementation 'io.grpc:grpc-protobuf:1.29.0'
implementation 'io.grpc:grpc-stub:1.29.0'
}
sourceSets {
main {
proto {
srcDir 'src/main/proto'
}
java {
srcDirs 'src/main/java', 'generated-sources/main/java'
}
}
}
protobuf {
protoc {
artifact = 'com.google.protobuf:protoc:3.11.0'
}
plugins {
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.29.0'
}
}
generateProtoTasks.generatedFilesBaseDir = 'generated-sources'
generateProtoTasks {
all().each { task ->
// Here you can configure the task
}
ofSourceSet('main')
}
}
From what I understood, everything's there: the grpc and protoc dependencies, and the plugin which enables protoc to compile grpc (protoc-gen-grpc), and where to deposit the generated files.
However, there are two problems:
the generated-sources are not marked as source or anything like that, meaning they cannot be imported from other classes
if I'm not mistaken, the generated-sources should generate a skeleton of DataRepoImpl so that I can add the code needed for BuscarData. However, it didn't. Or maybe I should create it, extending from DataRepo.java, but I couldn't test it, due to problem n°1.
I've added a screenshot of the project file structure:
img
As you can see, quite a lot (if not all) of the gradle settings are copy-pasted and scavenged from many different web-sites. I hope I was careful enough not to repeat any imports. There are similar questions, and I tried the solutions there, but no luck there. One example, with which I knew I had to include the gen grpc plugin: another SO question
Any tip regarding anything else is welcome! I'm new to stackoverflow question-asking, so I may have made mistakes regarding the question specificity or aim of the question.
Thanks!
Franri.
For 1), the plugin should put the generated files are the input for java compile tasks even if you do not explicitly add 'generated-sources/main/java' in the sourceSets configuration. Version 0.8.8 has been a while, you can try with newer versions. There might have been some minor fixes for things you may hit.
For 2), you did not add grpc plugin to each generateProto task. It should be
generateProtoTasks {
all().each { task ->
task.plugins { grpc{} }
}
ofSourceSet('main')
}

creating a custom gradle task to source mysql schema

I'm trying to write a custom Gradle task that would source mysql create and insert statements from a .sql file. This is what I've come up with :-
task initdb() {
def mysql = buildscript.configurations.classpath.find { it.toString().contains("mysql-connector-java") }
// URLClassLoader loader = GroovyObject.class.classLoader
def db = [url: "jdbc:mysql://127.0.0.1/",
user: "root", password: "admin", driver: 'com.mysql.cj.jdbc.Driver']
def sql = groovy.sql.Sql.newInstance(db.url, db.user, db.password, db.driver)
}
I'm getting an error saying Driver class not found. What am I doing wrong here?
The classpath of a Gradle task and the classpaths of your project are not the same thing.
Also the configuration and the execution of a Gradle task are two different things.
You would need the following:
buildscript {
repositories {
mavenCentral() // assuming your driver can be found there, if not, a custom repository
}
dependencies {
// Add the driver, and its dependencies, to the buildscript classpath
classpath "<driver dependency coordinates>"
}
}
task initdb() {
doLast {// Make sure the code is run during execution phase and not configuration phase
def mysql = buildscript.configurations.classpath.find { it.toString().contains("mysql-connector-java") }
// URLClassLoader loader = GroovyObject.class.classLoader
def db = [url: "jdbc:mysql://127.0.0.1/",
user: "root", password: "admin", driver: 'com.mysql.cj.jdbc.Driver']
def sql = groovy.sql.Sql.newInstance(db.url, db.user, db.password, db.driver)
}
}

Gradle is publishing source and Javadoc JARs, but not source JAR

I'm new to Gradle and attempting to publish a simple project to Maven Central. My build.gradle script is nearly identical to the example in their documentation but my primary/compiled JAR is not being uploaded. Source JAR, Javadoc JAR, etc. are uploading fine but not the compiled one.
When publishing local via publishToMavenLocal everything works as expected. I'll note that I'm using version 6.0.1 and using publishMavenJavaPublicationToMavenRepository to publish to Central.
What am I missing? How can I get my compiled JARs to Central?
Update: I just realized that the POM isn't being uploaded either.
Here is the complete build.gradle:
plugins {
id 'java-library'
id 'maven-publish'
id 'signing'
}
repositories {
jcenter()
mavenCentral()
}
dependencies {
implementation 'com.squareup.okhttp3:okhttp:4.0.1'
implementation 'com.squareup.moshi:moshi:1.9.1'
implementation 'com.squareup.moshi:moshi-adapters:1.9.1'
implementation 'com.google.guava:guava:28.0-jre'
api 'org.apache.commons:commons-math3:3.6.1'
testImplementation 'junit:junit:4.12'
}
group = 'com.acme'
version = '0.0.1-SNAPSHOT'
ext.isReleaseVersion = !version.endsWith("SNAPSHOT")
java {
withJavadocJar()
withSourcesJar()
}
publishing {
publications {
mavenJava(MavenPublication) {
artifactId = 'thttpd'
from components.java
pom {
name = 'thttpd'
licenses {
license {
name = 'The MIT License (MIT)'
url = 'https://opensource.org/licenses/MIT'
}
}
scm {
connection = 'scm:git:https://acme.com'
developerConnection = 'scm:git:https://acme.com'
url = 'https://acme.com'
}
}
}
}
repositories {
// Maven Central
maven {
def releasesRepoUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'
def snapshotsRepoUrl = 'https://oss.sonatype.org/content/repositories/snapshots/'
url = isReleaseVersion ? releasesRepoUrl : snapshotsRepoUrl
credentials {
username = nexusUsername
password = nexusPassword
}
}
}
}
signing {
required { isReleaseVersion && gradle.taskGraph.hasTask("publish") }
if( required ) {
sign publishing.publications.mavenJava
}
}
I had the same issue that Alexis mentions above, on the GitHub Packages web UI the sources and java-doc where not showing up. But on s01.oss.sonatype.org I was able to see them. Using Gradle 6.7

Apache Derby via Gradle: No suitable driver found for jdbc:derby

I have worked with Apache Derby before, but I have never used it in a Gradle Project. I have created a simple Derby Database in the root of my project using ij Derby tool by running the following commands:
connect 'jdbc:derby:MyDbTest;create=true';
CREATE TABLE Hashes (
string_id int,
RandString varchar(255)
);
INSERT INTO Hashes (string_id, RandString) values (1, 'sdfdsfsw');
SELECT * FROM Hashes;
After this, my Java Code in Main.java looks like:
package com.company;
import java.io.File;
import java.sql.*;
public class Main {
public static void main(String[] args) {
System.out.println("Current working directory : "+ new File(".").getAbsolutePath());
try {
Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
} catch (Exception e) {
e.printStackTrace(); //Does not get executed!
}
Connection conn = null;
try
{
conn = DriverManager.getConnection("jdbc:derby:MyDbTest"); //Exception here!!
System.out.println("Connected to database MyDbTest");
Statement s = conn.createStatement();
ResultSet rs = s.executeQuery(
"select string_id, RandString from Hashes");
while(rs.next()) {
int string_id = rs.getInt("string_id");
String randString = rs.getString("RandString");
System.out.printf("string_id: %s, RandString: %s\n", string_id, randString);
}
}
catch (SQLException sqle)
{
printSQLException(sqle);
} finally {
try {
if (conn != null) {
conn.close();
DriverManager.getConnection("jdbc:derby:;shutdown=true;deregister=false");
}
} catch (SQLException sqle) {
printSQLException(sqle);
}
}
}
public static void printSQLException(SQLException e)
{
//According to this page:
//https://db.apache.org/derby/papers/DerbyTut/embedded_intro.html
//" A clean shutdown always throws SQL exception XJ015, which can be ignored."
if(e.getSQLState().equals("XJ015")) return; //Ignore
// Unwraps the entire exception chain to unveil the real cause of the
// Exception.
while (e != null)
{
System.err.println("\n----- SQLException -----");
System.err.println(" SQL State: " + e.getSQLState());
System.err.println(" Error Code: " + e.getErrorCode());
System.err.println(" Message: " + e.getMessage());
// for stack traces, refer to derby.log or uncomment this:
e.printStackTrace(System.err);
e = e.getNextException();
}
}
}
I seem to be able to load the ClientDriver initially, but then when I try to get a connection to the Database I get the Exception. The first line ensures the Current Working Directory is the root of my project where the MyDbTest database is located.
My build.gradle file looks like:
apply plugin: 'java'
apply plugin:'application'
mainClassName = "com.company.Main"
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
compile group: 'org.apache.derby', name: 'derbyclient', version: '10.14.1.0'
compile group: 'org.apache.derby', name: 'derbytools', version: '10.14.1.0'
runtime group: 'org.apache.derby', name: 'derbyclient', version: '10.14.1.0'
runtime group: 'org.apache.derby', name: 'derbytools', version: '10.14.1.0'
}
A gradle run gives me:
Current working directory : /Users/<myname>/Documents/sources/tempFive/.
----- SQLException -----
SQL State: 08001
Error Code: 0
Message: No suitable driver found for jdbc:derby:MyDbTest
java.sql.SQLException: No suitable driver found for jdbc:derby:MyDbTest
at java.sql.DriverManager.getConnection(DriverManager.java:689)
at java.sql.DriverManager.getConnection(DriverManager.java:270)
at com.company.Main.main(Main.java:25)
I have made sure that my Derby Client and my version of the Derby Database is the same. I'm on Mac OSX 10.12 using IntelliJ 2017.3 and Java 8 update 151 if that helps.
EDIT: Why this question is different
I have worked with Apache Derby before and I can get this code to work without Gradle. The two causes of this exception mentioned in the answer to the other question are:
The driver is not loaded. . - If this is true, then why do I not get an exception at the top where I try to load the ClientDriver (Or should I try to load some other class to exclude this possibility.)
The JDBC URL is malformed. - I don't have a problem with this JDBC URL in a non-Gradle Project, so I don't think my URL is wrong. Please correct me if this is incorrect though.
EDIT: Solution (Thanks to Mark Rotteveel)
I was apparently unaware that I was using the Embedded Driver and not the Client Driver. When I used this without Gradle, I used to put all the jars in the entire Derby Lib directory in the classpath without bothering about what was used and what wasn't. My bad. So the first thing to change would be delete the try catch in my main() method:
try {
Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
} catch (Exception e) {
e.printStackTrace(); //Does not get executed!
}
The ClientDriver is never used, so there is no point in loading it. Next, as Mark Rotteveel pointed out I only need to depend on org.apache.derby:derby. This was my real mistake, so I put below the complete corrected build.gradle file:
apply plugin: 'java'
apply plugin:'application'
mainClassName = "com.company.Main"
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
compile group: 'org.apache.derby', name: 'derby', version: '10.14.1.0'
}
This is all I needed.
You are using the wrong Derby driver, by using derbyclient, you specify that you want to use the Derby (network) client driver, which supports the URL:
jdbc:derby://server[:port]/databaseName[;URLAttributes=value[;...]]
Your URL doesn't match, so it is rejected by the driver, and eventually java.sql.DriverManager will report that it didn't find a suitable driver.
Instead you need to use the dependency org.apache.derby:derby, as you seem to want to use the Derby Embedded driver. This driver is included in the full derby package, which also includes the Derby database itself, but not in derbyclient. This driver supports URL format:
jdbc:derby:databaseName;URLAttributes
Alternatively you do want to connect to an externally running Derby server, and in that case you are using the wrong URL.
See also Libraries provided by Derby and Database connection URL.

Android Studio connection MongoDB: Gradle build finished with 1 error

I need help to setup a direct connection to a MongoDB database (locally) using Android Studio on a Linux Mint 17.1 machine.
I made a new & clean project in Android Studio as you can see below.
After that I made new Java Class with the following code:
package com.example.bebo.connection;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import java.util.Set;
public class MongoPortal {
public boolean insert(){
try {
MongoClient mongoClient = new MongoClient( "localhost" , 27107 );
DB db = mongoClient.getDB("test");
// Get and print all the collections
Set<String> colls = db.getCollectionNames();
for (String s : colls)
System.out.println(s);
mongoClient.close();
}
catch (Exception e){
e.printStackTrace();
return false;
}
return true;
}
}
Last but not least, I changed the dependencies at build.gradle(Module: app) to:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'org.mongodb:mongo-java-driver:3.0.0'
compile 'com.android.support:appcompat-v7:22.0.0'
compile 'com.android.support:support-v4:18.0.0'
}
Building..
Output:
I just need the easiest way to setup a connection, but I can't figure out what I am missing here. Everything is installed correctly as far as I know.
This happened to me twice both the times the problem was with dependencies. This as far as I know this happens if you have same library with different versions (for me it was appcompat) or if you forget to list any dependency that needs to be listed.
Can you verify all jar files you have in lib folder (worst case by removing one by one) and also check dependencies once. Especially appcompat.
hope this helps.

Categories