Dynamic snowflake jdbc connection in java - java

I was trying to create a dynamic JDBC connection in java to connect to snowflake.
I am stuck at a point ,how can i pass the parameter from my property file into snowflake connection file
Please find the attached code
package com.cisco.export.utils;
import java.sql.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import com.cisco.config.Configuration;
public class SFDbConnection {
public Connection getConnection(Configuration config) throws SQLException{
Connection connection=null;
try {
System.out.println(config.getProp("sf.driverclass"));
System.out.println(config.getProp("sf.url"));
System.out.println(config.getProp("sf.account"));
System.out.println(config.getProp("sf.username"));
System.out.println(config.getProp("sf.password"));
System.out.println(config.getProp("sf.warehouse"));
System.out.println(config.getProp("sf.db"));
System.out.println(config.getProp("sf.schema"));
System.out.println(config.getProp("sf.role"));
Class.forName(config.getProp("sf.driverclass"));
String connectStr = "jdbc:snowflake://mysnowflakeaccount.us-east-1.snowflakecomputing.com";
connection = DriverManager.getConnection()
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return connection;
}
Can some one Help me how can i make the parameters inside the getConnection() dynamic.
Appreciate your help.
Thanks,
Nikhil

The Snowflake JDBC Driver accepts connection properties via the connection-string or via a java.util.Properties class object.
Using the properties in a connection string:
String sfAccount = config.getProp("sf.account");
String sfUsername = config.getProp("sf.username");
String sfPassword = config.getProp("sf.password");
String sfWarehouse = config.getProp("sf.warehouse");
String sfDatabase = config.getProp("sf.db");
String sfSchema = config.getProp("sf.schema");
String sfRole = config.getProp("sf.role");
String connectionString =
String.format("jdbc:snowflake://%s.snowflakecomputing.com/?role=%s&warehouse=%s&db=%s&schema=%s",
sfAccount,
sfRole,
sfWarehouse,
sfDatabase,
sfSchema
);
return DriverManager.getConnection(connectionString, sfUsername, sfPassword);
The com.cisco.config.Configuration class is not a known public API type, but if it can be translated to a java.util.Properties object, you can pass it when building a connection. Here's a direct conversion:
java.util.Properties props = new java.util.Properties();
String connectionString =
String.format(
"jdbc:snowflake://%s.snowflakecomputing.com",
config.getProp("sf.account")
);
props.setProperty("user", config.getProp("sf.username"));
props.setProperty("password", config.getProp("sf.password"));
props.setProperty("role", config.getProp("sf.role"));
props.setProperty("warehouse", config.getProp("sf.warehouse"));
props.setProperty("db", config.getProp("sf.db"));
props.setProperty("schema", config.getProp("sf.schema"));
return DriverManager.getConnection(connectionString, props);

Related

How to connect to JDBC connecting string of local.settings.json?

I would like to write to SQL database by Java based Azure Functions.
I have SQLconnstring of JDBC in local.settings.json. How to get this connection correctly from settings file instead of hard coding to java file?
package com.function;
import com.microsoft.azure.functions.annotation.*;
import com.microsoft.azure.functions.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* Azure Functions with Azure Storage Queue trigger.
*/
public class TopicTriggerSQLOutput {
/**
* This function will be invoked when a new message is received at the specified path. The
message contents are provided as input to this function.
*/
#FunctionName("TopicTriggerSQLOutput")
public void run(
#ServiceBusTopicTrigger(
name = "message",
topicName = "newtopic",
subscriptionName = "newsubscription",
connection = "topicconnstring"
) String message,
final ExecutionContext context
) {
/*Creating SQL Connection. I need help here:
*/
/*How to get connection string from local.settings.json instead of hard coding?*/
String connectionUrl =
"jdbc:sqlserver://yourserver.database.windows.net:1433;"
+ "database=AdventureWorks;"
+ "user=yourusername#yourserver;"
+ "password=yourpassword;"
+ "encrypt=true;"
+ "trustServerCertificate=false;"
+ "loginTimeout=30;";
try (Connection connection = DriverManager.getConnection(connectionUrl);) {
// SQL Code here.
}
// Handle any errors that may have occurred.
catch (SQLException e) {
e.printStackTrace();
}
//context.getLogger().info(message);
}
}
You can use System.getenv("") to get the value from local.settings.json file. For example, we can use String connectionUrl =System.getenv("SQLConnectionString"); to get the sql connection string in the local.settings.json file.

Cannot load connection class because of underlying exception: com.mysql.cj.exceptions.WrongArgumentException

Here is my code:
import java.sql.Connection;
import java.sql.DriverManager;
public class TestJdbc {
public static void main(String[] args) {
String jdbcUrl = "jdbc:mysql://localhost:3306?hb_student_tracker?useSSL=false&serverTimezone=UTC";
String user = "hbstudent";
String pass = "hbstudent";
try {
System.out.println("Conectiong to database: "+jdbcUrl);
Connection myConn =
DriverManager.getConnection(jdbcUrl,user,pass);
System.out.println("Connection succesful!!!");
}
catch(Exception ex) {
ex.printStackTrace();
}
}
}
It fails with the following error:
Conectiong to database:
jdbc:mysql://localhost:3306?hbstudent?useSSL=false&serverTimezone=UTC
java.sql.SQLNonTransientConnectionException: Cannot load connection class because of underlying exception:
com.mysql.cj.exceptions.WrongArgumentException: Malformed database URL,
failed to parse the connection string near '?useSSL=false&serverTimezone=UTC'.
What am I doing wrong?
You better check the documentation.
Probably, the problem is in URL. It should be a slash after port and before the database name.
String jdbcUrl = "jdbc:mysql://localhost:3306/hb_student_tracker?useSSL=false&serverTimezone=UTC";

Null URL in JDBC Connection

I am trying to connect with mysql with Java.
I am using db.properties files to get the connection details.
I am kind of new guy to work with the db.properties file. What is the wrong with my code??
It is as below
#mysql DB properties
#DB_DRIVER_CLASS=com.mysql.jdbc.Driver
#DB_URL=jdbc:mysql://localhost:8080/ci_intro
#DB_USERNAME=root
#DB_PASSWORD=
My Java Class file is
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
public class JDBCExample {
public static void main(String[] argv) throws IOException,
ClassNotFoundException, SQLException {
System.out
.println("-------- MySQL JDBC Connection Testing ------------");
Properties props = new Properties();
FileInputStream in = new FileInputStream("db.properties");
props.load(in);
in.close();
String driver = props.getProperty("DB_DRIVER_CLASS");
if (driver != null) {
Class.forName(driver);
}
String url = props.getProperty("DB_URL");
String username = props.getProperty("DB_USERNAME");
String password = props.getProperty("DB_PASSWORD");
Connection con = DriverManager.getConnection(url, username, password);
if (con != null) {
System.out.println("You made it, take control your database now!");
} else {
System.out.println("Failed to make connection!");
}
}
}
I'm getting below error
-------- MySQL JDBC Connection Testing ------------
Exception in thread "main" java.sql.SQLException: The url cannot be null
at java.sql.DriverManager.getConnection(Unknown Source)
at java.sql.DriverManager.getConnection(Unknown Source)
at com.avn.notificationengine.JDBCExample.main(JDBCExample.java:33)
Remove "#" in your *.properties file. All that follows "#" is comment. Your *.properties should be:
#mysql DB properties
DB_DRIVER_CLASS=com.mysql.jdbc.Driver
DB_URL=jdbc:mysql://localhost:8080/ci_intro
DB_USERNAME=root
DB_PASSWORD=

Storing Connection String in a String

How can I store my connection string
eg: "jdbc:oracle:thin:#local:testserver","scott","tiger"
in a String variable and pass that string to the connection?
what about
String connString = "jdbc:oracle:thin:#local:testserver";
pass that in to your connection:
Connection conn = DriverManager.getConnection(connString,"someUsername","somePassword");
Theres a tutorial on how to connect to oracle databases with Java here
Thin name service syntax: http://docs.oracle.com/cd/B28359_01/java.111/b31224/urls.htm#BEIDHCBA
If you need to supply other Oracle-specific connection properties then you need to use the long TNSNAMES style. The TNS format is:
jdbc:oracle:thin:#(description=(address=(host=HOSTNAME)(protocol=tcp)(port=PORT))(connect_data=(service_name=SERVICENAME)(server=SHARED)))
You can istantiate a String like this:
String connectionString = "jdbc:oracle:thin:#local:server";
and then use this String for connection, like Thousand wrote.
Anyway, I think that this code can't be reusable. It should be better to create a class connection like this:
import java.sql.Connection;
import java.sql.DriverManager;
public class ConectionTest {
static Connection getConnection() throws Exception {
String connectionString = "jdbc:oracle:thin:#local:server";
String driver = "com.mysql.jdbc.Driver";
String userName = "usertest";
String password = "pwdtest";
Class.forName(driver).newInstance();
Connection conn = DriverManager.getConnection(connectionString, userName,password);
return conn;
}
}
And then use the connection anywhere.

Any Way to Read JAAS Configuration File from Memory

We use JAAS in a heavily loaded web server. The configuration file is loaded from a file,
System.setProperty("java.security.auth.login.config", "/config/jaas.config");
During profiling, we noticed that the configuration is loaded from file for every login attempt. This is an I/O operation we try to avoid. Is there anyway to store the JAAS configuration in memory?
Following code snippet connects to a PostgreSQL database (using pgjdbc and HikariCP) with an in-memory JAAS configuration, that is, no Configuration files are required:
package com.vlkan.kerberos.auth;
import com.google.common.collect.ImmutableMap;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.Properties;
import static com.google.common.base.Preconditions.checkArgument;
public enum Main {
private static final String JAAS_CONFIG_NAME = "pgjdbc";
public static void main(String[] args) throws LoginException, SQLException {
String jdbcUrl = "jdbc:postgresql://host/dbname";
String jdbcDriver = "org.postgresql.Driver";
String username = "user";
String password = "pass";
Configuration jaasConfig = createJaasConfig();
Configuration.setConfiguration(jaasConfig);
HikariConfig hikariConfig = createHikariConfig(jdbcUrl, jdbcDriver, username, password);
HikariDataSource dataSource = new HikariDataSource(hikariConfig);
try (Connection connection = dataSource.getConnection()) {
try (PreparedStatement statement = connection.prepareStatement("SELECT 1")) {
try (ResultSet resultSet = statement.executeQuery()) {
boolean next = resultSet.next();
checkArgument(next, "no results");
int result = resultSet.getInt(1);
checkArgument(result == 1, "expecting: 1, found: %s", result);
System.out.println("ok");
}
}
}
}
private static HikariConfig createHikariConfig(String jdbcUrl, String jdbcDriver, String username, String password) {
HikariConfig config = new HikariConfig();
config.setDriverClassName(jdbcDriver);
config.setJdbcUrl(jdbcUrl);
config.setUsername(username);
config.setPassword(password);
fixKerberosProperties(config, username, password);
return config;
}
private static void fixKerberosProperties(HikariConfig config, String username, String password) {
Properties properties = new Properties();
properties.setProperty("user", username);
properties.setProperty("password", password);
properties.setProperty("JAASConfigName", JAAS_CONFIG_NAME);
config.setDataSourceProperties(properties);
}
private static Configuration createJaasConfig() {
// Create entry options.
Map<String, Object> options = ImmutableMap.of(
"useFirstPass", "false", // Do *not* use javax.security.auth.login.{name,password} from shared state.
"debug", "true" // Output debug (including plain text username and password!) messages.
);
// Create entries.
AppConfigurationEntry[] entries = {
new AppConfigurationEntry(
"com.sun.security.auth.module.Krb5LoginModule",
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
options)
};
// Create configuration.
return new Configuration() {
#Override
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
checkArgument(JAAS_CONFIG_NAME.equals(name));
return entries;
}
};
}
}
You could implement your own Configuration. The javadoc says:
The default Configuration
implementation can be changed by
setting the value of the
"login.configuration.provider"
security property (in the Java
security properties file) to the fully
qualified name of the desired
Configuration implementation class.
The default implementation com.sun.security.auth.login.ConfigFile (source) appears to load the file each time the class is instantiated. You could cache the contents. No comment on the security aspects either way.

Categories

Resources