Maven, can't see my h2 class - maven

I have some problem with my university project
I'm trying to connect to my h2 database but i'm failing on it.
I'm include it Maven dependencies but it still doesn't work.
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.186</version>
</dependency>
I get only classnotfoundexception
public class main {
public static void main(String[] a)
{
Class.forName("org.h2.Driver");
try (Connection conn = DriverManager.getConnection("jdbc:h2:~/test");
Statement stat = conn.createStatement()) {
stat.execute("create table test(id int primary key, name varchar(255))");
stat.execute("insert into test values(1, 'Hello')");
try (ResultSet rs = stat.executeQuery("select * from test")) {
while (rs.next()) {
System.out.println(rs.getString("name"));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
Any suggestion?

This is failing because the h2 db driver classes are not in the classpath at runtime. You should bundle them with your app's jar file, if they are not somehow made the part of the app's classpath.
Use maven-shade-plugin, or maven-jar-plugin to bundle the dependencies with your app's jar (in this case it is called the Uber jar) so as to make it single independent runnable jar.

Related

how to run cucumber test from java main method?

i have below code
package runner;
import java.util.stream.Stream;
public class PiccoloRunnerMain {
private static String[] defaultOptions = {
"--plugin", "pretty",
"--plugin", "html:target/fix-api-results.html",
"--plugin", "summary",
"--glue", "cukestep",
"--tags", "#T1",
"src/main/resources/features/"
};
public static void main(String args[]){
try{
Stream<String> cucumberOptions = Stream.concat(Stream.of(defaultOptions), Stream.of(args));
io.cucumber.core.cli.Main.main(cucumberOptions.toArray(String[]::new));
}catch(Exception e){
System.out.println(e);
}
}
}
but after generating uberjar file using gradle , when i run test its throwing error
java.lang.IllegalArgumentException: path must exist: /Users/abcd/repo/qa-orchestra/src/main/resources/features
how I to pass feature file to cucumber cli?
task uberJar(type: Jar) {
manifest {
attributes 'Main-Class': "$mainClassName"
}
from configurations.runtimeClasspath.findAll { it.name.endsWith('jar') }.collect { zipTree(it) }
baseName(project.name)
with jar
}
this is how I am generating jar file. or this is the issue with jar?
answer is here in one of the comments.
Running Cucumber tests directly from executable jar

NoClassDefFoundError in Osgi environment

I am working with osgi on apache karaf and I am trying to use kafka and debezium to run into an osgi environment.
kafka and debezium were not osgi ready (karaf will not consider them as bundles), so I did osgified them using eclipse "Plug-in project". The jars that I osgified them are the following : debezium-embedded, debezium-core, kafka connect-api, kafka connect-runtime.
At the begining I get alot of "Class not found exception" when I try to run debezium..
In order to resolve this problem, I changed the manifest of the two bundles. I added an import package to the caller and an export package to the called bundle. Using this I can solve the classNotFound issue.
After solving all the classNotfound issues, I get NoClassDefFoundError
NoClassDefFoundError means that the class loader could not find the .class when it tries to load them ... But I did import all the packages and export them as well.
Any thoughts how to deal with NoClassDefFoundError in an osgi environement
[EDIT Added code]
This is the class Monitor :
public class Monitor {
private Consumer<SourceRecord> consumer = new Consumer<SourceRecord>() {
public void accept(SourceRecord t) {
System.out.println("Change Detected !");
}
};
public void connect() {
System.out.println("Engine Starting");
Configuration config = Configuration.create()
/* begin engine properties */
.with("connector.class", "io.debezium.connector.mysql.MySqlConnector")
.with("offset.storage", "org.apache.kafka.connect.storage.FileOffsetBackingStore")
.with("offset.storage.file.filename", "d:/pathTooffset.dat")
.with("offset.flush.interval.ms", 60000)
/* begin connector properties */
.with("name", "my-sql-connector").with("database.hostname", "localhost").with("database.port", 3306)
.with("database.user", "root").with("database.password", "apassword").with("server.id", 10692)
.with("database.server.name", "localhost")
.with("database.history", "io.debezium.relational.history.FileDatabaseHistory")
.with("database.history.file.filename", "d:/pathTOdbhistory.dat")
.build();
try {
// Create the engine with this configuration ...
EmbeddedEngine engine = EmbeddedEngine.create().using(config).notifying(consumer).build();
Executor executor = Executors.newFixedThreadPool(1);
executor.execute(() -> {
engine.run();
});
} catch (Exception e) {
e.printStackTrace();
}
}
And my activator :
public class Activator implements BundleActivator {
public void start(BundleContext context) throws Exception {
Monitor monitor = new Monitor();
monitor.connect();
}
public void stop(BundleContext context) throws Exception {
}}
The problem must be inside EmbeddedEngine. The error could not initialize class means that some static initialization of the class did not work. See this related question noclassdeffounderror-could-not-initialize-class-error.
I propose to run karaf in debug mode and debug through the initialization of this class.

How to run drill in non installed system with jar file?

I'm making the program using Apache drill 1.8.
I'm trying to run this program in non-drill installed HDFS.
The way I think is using jar file, drill contained jar file can run this program because it is running in virtual machine.
But I'm not confident this way. Can it work?
If this way works, How to contain drill in jar file?
If not, what kind of way?
Plus question, how to change storage configuration using Java code?
It does not matter drill or hdfs running on the same machine or not.
Why do you need to create a jar.
If you are using Maven as building tool, add Drill JDBC driver dependency:
<dependency>
<groupId>org.apache.drill.exec</groupId>
<artifactId>drill-jdbc</artifactId>
<version>1.8.0</version>
</dependency>
Sample code:
public class TestJDBC {
// Host name of machine on which drill is running
public static final String DRILL_JDBC_LOCAL_URI = "jdbc:drill:drillbit=192.xxx.xxx.xxx";
public static final String JDBC_DRIVER = "org.apache.drill.jdbc.Driver";
public static void main(String[] args) throws SQLException {
try {
Class.forName(JDBC_DRIVER);
} catch (ClassNotFoundException ce) {
ce.printStackTrace();
}
try (Connection conn = new Driver().connect(DRILL_JDBC_LOCAL_URI, null);
Statement stmt = conn.createStatement();) {
String sql = "select employee_id,first_name,last_name from cp.`employee.json` limit 10";
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
System.out.print(rs.getInt("employee_id") + "\t");
System.out.print(rs.getString("first_name") + "\t");
System.out.print(rs.getString("last_name") + "\t");
System.out.println();
}
rs.close();
} catch (SQLException se) {
se.printStackTrace();
}
}
}

Embedding an H2 Database within the WEB-INF Directory

I have an embedded H2 Database I'd like to put in the WEB-INF directory of a web application.
What is the proper way to refer to this in a JDBC url?
Ideally I'd like a solution that would work both for a WAR, and an expanded WAR (If possible).
Thank-you for your help!
FYI, I've tried the following:
jdbc:h2:/WEB-INF/data/myDB;CIPHER=AES
But this results in:
org.h2.jdbc.JdbcSQLException: A file path that is implicitly relative to the current working directory is not allowed in the database URL "jdbc:h2:/WEB-INF/data/myDB;CIPHER=AES". Use an absolute path, ~/name, ./name, or the baseDir setting instead. [90011-187]
Changing this to:
jdbc:h2:./WEB-INF/data/myDB;CIPHER=AES
Results in the following error, which clearly shows its trying to put my database in Tomcat's bin directory, rather than the true WEB-INF directory where I want it:
org.h2.jdbc.JdbcSQLException: Error while creating file "C:/Program Files/Apache Software Foundation/Tomcat 7.0/bin/WEB-INF" [90062-187]
I managed to make the embedded solution work without AES like this:
try {
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection(
"jdbc:h2:" + getServletContext().getRealPath("/") +
"/WEB-INF/data/myDB", "sa", "");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM INFORMATION_SCHEMA.TABLES");
while (rs.next()) {
}
rs.close();
stmt.close();
conn.close();
} catch(SQLException e) {
} catch(ClassNotFoundException e) {
} finally {
}
This was tested with H2 1.3.176 on Tomcat8. It should work with H2 1.4 and CIPHER=AES provided the embedded database is already inside the war file I guess.
The idea is the following: you need to get the absolute path, and that deployment path may not be the same depending on how you deployed the war file.
So we need to use the servlet context and request the real path. For this we use getServletContext().getRealPath("/") and append /WEB-INF/data/myDB to it as per your needs.
I did not test the CIPHER=AES part as I've never used it.
Update:
Getting a good reference to the servlet context is tricky. One could use a raw request, get the underlying session and then get to the servlet context.
But it would be good to have the embedded H2 database opened as soon as the application is deployed/started in Tomcat, and closed properly as soon as the application is stopped.
In order to perform that, the use of a listener is needed. Here's what I propose as an update to my previous answer. This time the solution is complete with AES CIPHER and it should be easy to plug into your code.
Suggestion: the listener java code can be easily modified to start a H2 tcp server as well, useful to enable the automatic mixed mode (embedded+tcp).
Add 3 lines to the file web.xml:
<listener>
<listener-class>com.mine.MyServletContextListener</listener-class>
</listener>
File MyServletContextListener.java:
package com.mine;
import javax.servlet.*;
import java.sql.*;
public class MyServletContextListener implements ServletContextListener {
Connection conn;
public void contextInitialized(ServletContextEvent sce) {
try {
Class.forName("org.h2.Driver");
conn = DriverManager.getConnection( "jdbc:h2:" + sce.getServletContext().getRealPath("/") + "/WEB-INF/data/myDB;CIPHER=AES", "sa", "aespassword dbpassword");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM INFORMATION_SCHEMA.TABLES");
while (rs.next()) {
}
rs.close();
stmt.close();
} catch(SQLException e) {
} catch(ClassNotFoundException e) {
} finally {
}
}
public void contextDestroyed(ServletContextEvent sce) {
try {
conn.close();
} catch(SQLException e) {
} finally {
}
}
}

Cannot connect to Derby DB on netbeans using JDBC

I am trying to manipulate an Apache Derby DB on NetBeans and I'm having a tough time connecting.
It seems very simple but it just wouldn't connect.
Please help. Thanks in advance!
import java.sql.*;
public class JDBCtutorial {
private static String tableName = "Diseases";
private static Connection conn = null;
private static Statement stmt = null;
public static void createConnection() {
try {
Class.forName("org.apache.derby.jdbc.ClientDriver");
} catch(ClassNotFoundException cnfe) {
System.out.println(cnfe);
}
try {
conn = DriverManager.getConnection("jdbc:derby://localhost:1527/DBName", "user", "password");
} catch (Exception e) {
System.out.println("Cannot connect. . .");
}
}
public static void main(String[] args) {
createConnection();
}
}
You're using the driver for embedded use of Derby (org.apache.derby.jdbc.EmbeddedDriver), yet you try to connect over the network, in which case you should use the network driver, org.apache.derby.jdbc.ClientDriver.
All this is explained in detail in the Derby doc which is quite good.
Also, as probably getConnection is throwing an exception that might give some hints about the cause of the problem, try pinting the stacktrace, it should provide that info:
} catch (Exception e) {
System.out.println("Cannot connect:");
e.printStackTrace();
}
You Just need to add one library file in your project.
Download here
Eclipse : Right Click on project then > Build Path > Configure Build Path > Add External JAR (and select the file you downloaded) > Done
NetBeans : Right Click on project then > Properties > Libraries > ADD JAR/Folder
"and select the file you downloaded " > ok (Run)
Add Permanently : Add the file in c:/program files/java/JRE/lib/ folder

Resources