Connection issue in Hadoop MapReduce - java

In a Hadoop MapReduce program, I am trying to read JDBC connection details from connection.properties file, that is also in proper classpath.
Code:
public synchronized Connection getConnection() {
return getDetails(); // inside try catch block
}
public Connection getDetails() throws SQLException, IOException {
Properties props = new Properties();
FileInputStream in = new FileInputStream("connection.properties");
props.load(in);
in.close();
String drivers = props.getProperty("jdbc.drivers");
if (drivers != null) {
System.setProperty("jdbc.drivers",drivers);
}
String url = props.getProperty("jdbc.url");
String username = props.getProperty("jdbc.username");
String password = props.getProperty("jdbc.password");
return DriverManager.getConnection(url, username, password);
}
But when running my driver main program it gives an error:
java.io.FileNotFoundException: connection.properties (No such file or directory)
Any idea?

In order to run the MapReduce that uses properties file, you need to package it with your code, and instead of using the traditional reading the file streams from local system, you can read it from the jar you already built
reading properties from jar:
InputStream stream = this.getClass().getResourceAsStream("foo.properties"))

Related

Why does runtime loaded MySQL driver output "No suitable driver found"?

I tried to load MySQL driver when my application is running. So I made jar file loading method as "loadJobJars" to that be creating URLClassLoader object with given jar file list. And I was call Class.forName method and then DriverManager.getConnection method. But it was output "No suitable driver found" on terminal.
Is there anyone know why this be happened?
My code is below.
public DBConnectionManager(Path jarPath) throws MalformedURLException {
this.urlClassLoader = loadJobJars(listJarFiles(jarPath));
}
public Connection createConnection(String dbName, String host, int port, String db, String user,
String password) throws NoSuchFieldException, SecurityException, IllegalArgumentException,
IllegalAccessException, ClassNotFoundException, SQLException, InstantiationException {
dbName = dbName.toLowerCase();
String url = "jdbc:" + dbName + "://" + host + ":" + port + "/" + db;
String driverName = DBDriver.getDriverName(dbName.toUpperCase());
Logger.getInstance().info("connection url: "+url+" driver: "+driverName);
Class.forName(driverName, true, this.urlClassLoader);
Connection conn = DriverManager.getConnection(url, user, password); //Here is it was happened code line.
return conn;
}
public URLClassLoader loadJobJars(File[] jarFiles) throws MalformedURLException {
URL[] urls = Arrays.asList(jarFiles).stream().map(f -> {
try {
System.out.println(f.getAbsolutePath());
return f.toURI().toURL();
} catch (MalformedURLException e) {
e.printStackTrace();
}
return null;
}).filter(u -> u != null).toArray(URL[]::new);
return URLClassLoader.newInstance(urls, ClassLoader.getPlatformClassLoader());
}
public File[] listJarFiles(Path jarPath) {
return jarPath.toFile().listFiles(new FilenameFilter() {
#Override
public boolean accept(File dir, String name) {
return name.endsWith(".jar");
}
});
}
Console output is below.
[INFO][DBConnectionManager:77][20210119152004] connection url: jdbc:mysql://localhost:3306/mysql driver: com.mysql.jdbc.Driver
Exception in thread "main" java.sql.SQLException: No suitable driver found for jdbc:mysql://192.168.1.157:3306/mysql
at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:702)
at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:251)
at com.innotree.innoquartz.iqjobgen.DBConnectionManager.createConnection(DBConnectionManager.java:35)
at com.innotree.innoquartz.iqjobgen.DBConnectionManager.main(DBConnectionManager.java:77)
The way DriverManager creates connections is sensitive to the class loader of the calling code. The Driver used to create the connection must be visible to the class loader of the calling class (or when the calling code has no class loader, the context class loader). The driver you loaded is not visible to the class loader of the calling code, so DriverManager will not use the driver to create a connection.
You must create the connection using code that uses the same class loader (or at least where the class loader with the driver is visible). Alternatively, you need to use the java.sql.Driver directly, skipping DriverManager altogether.
Thank for your kind answer.
I saw your answer and finally figure out the problem by direct loading MySQL driver. Your help was very useful to solve that. Solution code is down below.
String url = "jdbc:mysql://localhost:3306/mysql";
URLClassLoader loader = new URLClassLoader(urls, ClassLoader.getSystemClassLoader());
Class cls = loader.loadClass("com.mysql.jdbc.Driver");
Driver driver = (Driver)cls.newInstance();
Properties info = new Properties();
info.put("user", "admin");
info.put("password", "1234");
Connection conn = driver.connect(url, info);

Setting up a remote Derby DB: "No suitable driver found" error

I am trying to set up a remote Derby database just for practice. The following code works without a problem whenever I access the DB on my harddrive:
class Test{
public static void main(String[] args) {
String protocol = "jdbc:derby:";
// String dbPath = "C:/Java_Practice/derbyDB"; // this dbPath works...
String dbPath = "//108.167.141.127/derbyDB"; // and this one doesn't
String url = protocol + dbPath;
try( Connection conn = DriverManager.getConnection(url) )
{
System.out.println(conn);
}
catch(SQLException e){
System.out.println(e.getMessage());
}
}
}
I then uploaded the whole derbyDB directory to my Hostgator-hosted website, obtained its IP by pinging the server and edited the dbPath var accordingly. The code stopped working as if it can't even see the DB. What am I missing?
Looks like your driver class not loaded.
Try loading it before calling DriverManager.getConnection, and see if it works.
String driver = "org.apache.derby.jdbc.ClientDriver";
Class.forName(driver).newInstance();
String protocol = "jdbc:derby:";
String dbPath = "//108.167.141.127/derbyDB"+";create=true";
String url = protocol + dbPath;
Connection conn = DriverManager.getConnection(url);
Answering my own question after some digging.
This is what I found in the official Apache Derby documentation (https://db.apache.org/derby/docs/10.0/manuals/develop/develop14.html):
You can specify only databases that are local to the machine on which
the JVM is running.
Looks like what I wanted to accomplish cannot be done...

Java8-Maven No suitable jdbc driver found

I need help with my project when I try to run the project using myBatis, SQL Connector and Maven and I just get that error:
"no suitable jdbc driver found"
I have no clue how to fix this from now on.
public void openConnection() throws IOException, SQLException {
///database/src/main/java/Mappers/
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
session = sqlSessionFactory.openSession();
updateData();
}
private void updateData() {
int createTable = session.update("database.resources.createTableToTest");
int addTable = session.update("database.resources.addToTest");
test();
}
You have to set classpath for your connector.jar in eclipse using build path and
You also have to put connector.jar to the lib folder of WEB-INF Directory.

Reading Config File Contents

I am trying to read a "DB_Config_File.properties" file but for some reason the following error is occurring:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:186)
My class that is handling the reading of the config file looks like the following:
public class database {
public static Connection conn;
public static void dbConnection() throws FileNotFoundException, IOException, ClassNotFoundException, SQLException {
Properties props = new Properties();
driver = props.getProperty("driver");
String url = props.getProperty("url");
String username = props.getProperty("username");
String password = props.getProperty("password");
String configFile = "F:/Project/Java Project/src/mainScreen/DB_Config_File.properties";
InputStream ins = new FileInputStream(configFile);
props.load(ins);
Class.forName(driver);
conn = DriverManager.getConnection(url, username, password);
}
Judging by the error I am guessing there is something wrong in the "Class.forName(driver)" part.
Can you please help me out here?
Thanks
You are loading the properties file from the input stream after you are reading values from it. The variable 'driver' is null as the properties are empty and is causing the NPE.

Reading From Config File Outside Jar Java

Currently I am trying to read my config file from root of project directory, in order to make this actual configuration I want to move this to external location and then read from there.
Adding a complete path in following code throws out error :
package CopyEJ;
import java.util.Properties;
public class Config
{
Properties configFile;
public Config()
{
configFile = new java.util.Properties();
try {
// configFile.load(this.getClass().getClassLoader().getResourceAsStream("CopyEJ/config.properties"));
Error Statement ** configFile.load(this.getClass().getClassLoader().getResourceAsStream("C://EJ_Service//config.properties"));
}catch(Exception eta){
eta.printStackTrace();
}
}
public String getProperty(String key)
{
String value = this.configFile.getProperty(key);
return value;
}
}
Here's the error:
java.lang.NullPointerException
at java.util.Properties$LineReader.readLine(Properties.java:365)
at java.util.Properties.load(Properties.java:293)
at CopyEJ.Config.<init>(Config.java:13)
at CopyEJ.CopyEJ.main(CopyEJ.java:22)
Exception in thread "main" java.lang.NullPointerException
at java.io.File.<init>(File.java:194)
at CopyEJ.CopyEJ.main(CopyEJ.java:48)
How can I fix this ?
The purpose of method getResourceAsStream is to open stream on some file, which exists inside your jar. If you know exact location of particular file, just open new FileInputStream.
I.e. your code should look like:
try (FileInputStream fis = new FileInputStream("C://EJ_Service//config.properties")) {
configFile.load(fis);
} catch(Exception eta){
eta.printStackTrace();
}
This line requires your config.properties to be in the java CLASSPATH
this.getClass().getClassLoader().getResourceAsStream("C://EJ_Service//config.properties")
When it is not, config.properties won't be accessible.
You can try some other alternative and use the configFile.load() function to read from.
One example would be:
InputStream inputStream = new FileInputStream(new File("C:/EJ_Service/config.properties"));
configFile.load(inputStream);

Categories

Resources