SQLiteCantOpenDatabaseException caught but still displaying error log - java

I am trying to open a database to test if the database exists. I wrote the code in a try and catch statement to catch the SQLiteCantOpenDatabaseException if the database doesn't exist.
However, even if I catch the SQLiteCantOpenDatabaseException, the error log is printed in the Logcat. Is that normal ? I haven't invoked the method printStackTrace on the exception. Is there a way to remove the exception log ?
Fortunately, the app still runs normaly even after the try and catch statement.
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
myContext = this;
try
{
database = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null,
SQLiteDatabase.OPEN_READWRITE);
database.close();
Log.v("Database Log", "Database exists !!");
}
catch(SQLiteCantOpenDatabaseException e)
{
// The database doesn't exist; Lets create it
Log.v("Database Log", "Database doesn't exists !!");
}
Logcat
17:30:43.587: E/SQLiteLog(2054): (14) cannot open file at line 30191 of [00bb9c9ce4]
17:30:43.587: E/SQLiteLog(2054): (14) os_unix.c:30191: (2) open(/data/data/com.appsplus.hearthstonecollection/databases/hearthstonedata) -
17:30:43.667: E/SQLiteDatabase(2054): Failed to open database '/data/data/com.appsplus.hearthstonecollection/databases/hearthstonedata'.
17:30:43.667: E/SQLiteDatabase(2054): android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database

Related

Rollback is working on a transaction but crashes anyway by SQLNonTransientConnectionException

I'm working on a cinema ticketing java application.
There is a grid of chairs, the user selects all chairs to book, then press ok to book it (insert rows in a mysql database). If any of the bookings pretended to do fails due to duplicate entries, all of them are rollbacked.
To do it, listening button "buy" I do:
case "buy":
try {
boolean success = true;
for(Booking b : bookingsToDo) {
if(DbConnect.getConnection().getAutoCommit())
DbConnect.getConnection().setAutoCommit(false);
success = controllerBooking.insertBooking(b);
if(!success) {
JOptionPane.showMessageDialog(frameMain, "Error occurred, booking failed");
DbConnect.getConnection().rollback();
}
}
if(success) {
JOptionPane.showMessageDialog(frameMain, "Booking done");
DbConnect.getConnection().commit();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
This is working, because actually all the bookings are being reversed.
But anyway is throwing: java.sql.SQLNonTransientConnectionException:
Can't call rollback when autocommit=true
so the program fails then.
How is it possible that rollback is working and at the same time throwing a "Can't rollback" message? And how could it be when I'm doing setAutoCommit(false) in every loop?
DbConnect.getConnection() is getting a new connection each time its called.
Autocommit is set on a per connection basis. Therefore you are rolling back on a different connection. The controllerBooking also needs a connection reference to use the same connection.
So:
con = DbConnect.getConnection();
con.setAutoCommit(false);
for(Booking b : bookingsToDo) {
success = controllerBooking.insertBooking(con, b);
if(!success) {
JOptionPane.showMessageDialog(frameMain, "Error occurred, booking failed");
con.rollback();
break;
}
}
con.commit();

java.lang.ClassNotFoundException while executing DB connection statements

I have set of DB connection statements in my java file which takes the driver name, url, username and password from my property file and then try to make a connection. But I am keep getting error exactly in this try block . My code is
try {
Class.forName(properties.getProperty("DB2.database.driver"));
} catch (Exception e) {
System.err.println("Unable to locate database driver:" + e);
return null;
}
The error message is
Unable to locate database `driver:java.lang.ClassNotFoundException:
May i know why it is keep getting this error?

False SQLite error? code 14

I have encountered a weird problem. I was querying a database table for a list of words and was able to get the list. But I am not being able to update that table. The weird thing is, the logcat is showing Code 14 error. I uninstalled the app, re-ran it so the db is freshly copied, But nothing has changed.
Here's the dbHandler code:
public VocabDatabase(Context context) {
super(context, DB_NAME, null, 1);
this.myContext = context;
this.DB_PATH = context.getApplicationInfo().dataDir + "/databases/";
}
/**
* Creates a empty database on the system and rewrites it with your own database.
*/
public void createDataBase() throws IOException {
boolean dbExist = checkDataBase();
if (dbExist) {
//do nothing - database already exist
} else {
//By calling this method and empty database will be created into the default system path
//of your application so we are gonna be able to overwrite that database with our database.
this.getWritableDatabase();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
/**
* Check if the database already exist to avoid re-copying the file each time you open the application.
*
* #return true if it exists, false if it doesn't
*/
private boolean checkDataBase() {
this.getReadableDatabase();
SQLiteDatabase checkDB = null;
try {
String myPath = DB_PATH;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
} catch (SQLiteException e) {
e.printStackTrace();
}
if (checkDB != null) {
checkDB.close();
}
return (checkDB != null) ? true : false;
}
private boolean checkDataBaseAlt(){
File chkdb = new File(DB_PATH);
return chkdb.exists();
}
/**
* Copies your database from your local assets-folder to the just created empty database in the
* system folder, from where it can be accessed and handled.
* This is done by transfering bytestream.
*/
private void copyDataBase() throws IOException {
//Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(DB_NAME);
// Path to the just created empty db
String outFileName = DB_PATH + DB_NAME;
//Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
//transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length = 0;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
public void openDataBase() throws SQLException {
//Open the database
String myPath = DB_PATH + DB_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
}
#Override
public synchronized void close() {
if (myDataBase != null)
myDataBase.close();
super.close();
}
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (newVersion > oldVersion) {
try {
copyDataBase();
} catch (Exception e) {
e.printStackTrace();
}
}
}
// Add your public helper methods to access and get content from the database.
// You could return cursors by doing "return myDataBase.query(....)" so it'd be easy
// to you to create adapters for your views.
//add your public methods for insert, get, delete and update data in database.
public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) {
SQLiteDatabase db = this.getWritableDatabase();
return db.query(table, columns, selection, selectionArgs, groupBy, having, orderBy);
}
public long insert(String table, String nullColumnHack, ContentValues contentValues) {
SQLiteDatabase db = this.getWritableDatabase();
return db.insert(table, nullColumnHack, contentValues);
}
public Cursor rawQuery(String string, String[] selectionArguments) {
SQLiteDatabase db = this.getWritableDatabase();
return db.rawQuery(string, selectionArguments);
}
public long update(String table, ContentValues contentValues, String whereClause, String[] whereArgs) {
SQLiteDatabase db = this.getWritableDatabase();
return db.update(table, contentValues, whereClause, whereArgs);
}
}
And here's the service code:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
vdb = new VocabDatabase(this);
Toast.makeText(this, "Service started", Toast.LENGTH_SHORT).show();
createDB();
queryDB();
return super.onStartCommand(intent, flags, startId);
}
private void createDB() {
vdb.getWritableDatabase();
try {
vdb.createDataBase();
vdb.openDataBase();
} catch (Exception e) {
e.printStackTrace();
}
}
public void queryDB() {
String vet = "";
ArrayList<String> lister = new ArrayList<>();
Cursor cr = vdb.query(TABLE_NAME, null, null, null, null, null, null);
if (cr.moveToFirst()) {
do {
lister.add(cr.getString(0));
} while (cr.moveToNext());
}
cr.close();
String vet="";
for (String v : lister) {
vet += v + "\t";
}
}
The String-vet is displayed in the toast, and I can see all the words in the first column of the table. But I'm not able to update the rows.
private void updateInDatabase(String up, String pot) {
ContentValues conval = new ContentValues();
conval.put(pot, "1");
try {
long res = vdb.update(TABLE_NAME, conval, "Word=?", new String[]{up});
} catch (Exception e) {
}
}
I've given the storage permissions to it and double checked the same.
Manifest File:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.hack.corrector">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:remove="android:maxSdkVersion"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".scrapeservice"/>
</application>
Error Log:
05-17 13:39:04.614 28088-28088/com.example.hack.corrector E/SQLiteLog: (14) cannot open file at line 31282 of [5a3022e081]
05-17 13:39:04.615 28088-28088/com.example.hack.corrector E/SQLiteLog: (14) os_unix.c:31282: (21) open(/data/user/0/com.example.hack.corrector/databases/) -
05-17 13:39:04.616 28088-28088/com.example.hack.corrector E/SQLiteDatabase: Failed to open database '/data/user/0/com.example.hack.corrector/databases/'.
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:207)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:191)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:806)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:791)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
at com.example.hakc.corrector.VocabDatabase.checkDataBase(VocabDatabase.java:81)
at com.example.hakc.corrector.VocabDatabase.createDataBase(VocabDatabase.java:48)
at com.example.hakc.corrector.scrapeservice.createDB(scrapeservice.java:48)
at com.example.hakc.corrector.scrapeservice.onStartCommand(scrapeservice.java:39)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3049)
at android.app.ActivityThread.access$2300(ActivityThread.java:154)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1479)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5571)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:745)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:635)
05-17 1
This issue if you are running your app on API level 23 or greater, because of the new real-time permissions model introduced in this. In these versions users grant permissions to apps while the app is running
For getting permissions at runtime, you will have to request the user. You can do that in following way:
Request Permission
String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permissions, REQUEST_CODE); //REQUEST_CODE can be any Integer value
And check your Permission Result
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE:
if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
//Permission granted.
//Now you can try your database creating and writing stuff.
}
else{
//Permission denied.
}
break;
}
}
If this does not solve your problem then go to this link. Number of solutions are here for the same problem.
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
Like the exception tells :
Failed to open database '/data/user/0/com.example.hack.corrector/databases/'.
You are trying to open the SQLite DB with the variable DB_PATH set like
this.DB_PATH = context.getApplicationInfo().dataDir + "/databases/";
You don't set the name of the file, only set the directory path. databases/ is a directory.
Set a file name to your path :
this.DB_PATH = context.getApplicationInfo().dataDir + "/databases/my_db";
EDIT:
you have two DB name variable... you are using DB_NAME to open the connection with the helper (in the super constructor) then in the check method you used DB_PATH.
So you are able to get a connection from the helper
this.getWritableDatabase(); //Using the DB at `DB_NAME`
But will failed to get a connection with
String myPath = DB_PATH;
SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
Because you used DB_PATH here not DB_NAME. You are using 2 different DB path.
I believe you will find that the cannot open database error is not actually a failure, but an indication of the issue. That is the open error is encountered by the checkdataBase method because it cannot open the database as the message says. This, as it is trapped, does not result in a failure.
Rather what happens is that checkDatabase method returns false, because it cannot open the database, and so the database is copied from the assets every time the App is run. Thus undoing any changes from a previous run.
It is simple to diagnose/debug this using two lines of code.
by adding Log.d("DBEXISTCHK", "Method checkdataBase returned" + String.valueOf(dbExist));
as per :-
/**
* Creates a empty database on the system and rewrites it with your own database.
*/
public void createDataBase() throws IOException {
boolean dbExist = checkDataBase();
Log.d("DBEXISTCHK", "Method checkdataBase returned" + String.valueOf(dbExist)); //<<<<<<<<<< ADDED
if (dbExist) {
//do nothing - database already exist
} else {
//By calling this method and empty database will be created into the default system path
//of your application so we are gonna be able to overwrite that database with our database.
this.getWritableDatabase();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
and
by adding Log.d("DBCOPY","Database is being copied from the Assets.");
as per :-
private void copyDataBase() throws IOException {
Log.d("DBCOPY","Database is being copied from the Assets."); //<<<<<<<<<< ADDED
//Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(DB_NAME);
// Path to the just created empty db
String outFileName = DB_PATH + DB_NAME;
//Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
//transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length = 0;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
The resultant log would then be along similar to (note the last two lines):-
05-17 10:12:22.591 1152-1152/bcdbfa.basiccopydbfromassets E/SQLiteLog: (14) cannot open file at line 30174 of [00bb9c9ce4]
(14) os_unix.c:30174: (21) open(/data/data/bcdbfa.basiccopydbfromassets/databases/) -
05-17 10:12:22.591 1152-1152/bcdbfa.basiccopydbfromassets E/SQLiteDatabase: Failed to open database '/data/data/bcdbfa.basiccopydbfromassets/databases/'.
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
at bcdbfa.basiccopydbfromassets.VocabDatabase.checkDataBase(VocabDatabase.java:85)
at bcdbfa.basiccopydbfromassets.VocabDatabase.createDataBase(VocabDatabase.java:45)
at bcdbfa.basiccopydbfromassets.MainActivity.onCreate(MainActivity.java:18)
at android.app.Activity.performCreate(Activity.java:5008)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
05-17 10:12:22.591 1152-1152/bcdbfa.basiccopydbfromassets W/System.err: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
05-17 10:12:22.599 1152-1152/bcdbfa.basiccopydbfromassets W/System.err: at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
at bcdbfa.basiccopydbfromassets.VocabDatabase.checkDataBase(VocabDatabase.java:85)
at bcdbfa.basiccopydbfromassets.VocabDatabase.createDataBase(VocabDatabase.java:45)
at bcdbfa.basiccopydbfromassets.MainActivity.onCreate(MainActivity.java:18)
at android.app.Activity.performCreate(Activity.java:5008)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
05-17 10:12:22.599 1152-1152/bcdbfa.basiccopydbfromassets D/DBEXISTCHK: Method checkdataBase returnedfalse
05-17 10:12:22.599 1152-1152/bcdbfa.basiccopydbfromassets D/DBCOPY: Database is being copied from the Assets.
The Fix
The fix is even simpler, it is simply a matter of changing :-
String myPath = DB_PATH;
to
String myPath = DB_PATH + DB_NAME;
in the checkDatabase method.
In which case the result in the log (if the logging is left in) will be :-
05-17 10:30:49.809 1265-1265/? D/DBEXISTCHK: Method checkdataBase returnedtrue
Additional
Re the comment
only empty database with the same name is being created.
This is because you are calling getWritableDatabase in the createDB method before calling the createDatabase method. That is, getWritableDatabase will, if there is no database, create an empty database (bar the sqlite_master table and for android the android_metadata table), and then invoke the onCreate method. So that explains why when the full path is correct that the copy of the database is circumvented and that the database empty database exists as a result.
And then the comment
But when I changed 'myPath' back to myPath = DB_Path; the entire
database got copied but the problem still persists.
When the path is incorrect the, as previously explained, the checkDatabase method will always return false and thus the copyDatabase method is invoked, this then works as the paths used are correct.
So
private void createDB() {
vdb.getWritableDatabase(); //<<<<<<<<<< The villainous line
try {
vdb.createDataBase();
vdb.openDataBase();
} catch (Exception e) {
e.printStackTrace();
}
}
should be
private void createDB() {
try {
vdb.createDataBase();
vdb.openDataBase();
} catch (Exception e) {
e.printStackTrace();
}
}
Obviously with all paths being the full path that include the name of the database.
I've figured out where the problem lies. It was in the service from which the query is done. In createDB() method, I've used vdb.getWritableDatabase(). When I commented it out, the query worked smoothly. Entire database copied, and queries are being handled perfectly. I need to check the 'update' though.. I sincerely thank you guys for hearing me and taking your time to help me solve this problem. It's thanks to your answers, I've learnt a lot about how databases are communicated with properly.

can't open database exception in android

i'm having problem understanding what is the error with opening the database since my program works fine but it displays this error.can anyone help me in understanding this.
this is how i check the database exists in the main
private boolean checkDataBase(){
SQLiteDatabase checkDB = null;
try {
checkDB = SQLiteDatabase.openDatabase("Event.db", null, SQLiteDatabase.OPEN_READONLY);
checkDB.close();
}
catch (SQLiteException e) {
eventDB = new DatabaseEvent(this);
}
return checkDB != null;
}
i'm getting this error i don't know how to fix?
E/SQLiteDatabase: Failed to open database 'MyACtion.db'.
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
In the onCreate method of DatabaseEvent class change the SQL from:
db.execSQL("CREATE TABLE... ;");
to
db.execSQL("CREATE TABLE... "); // NO SEMI-COLON
also, in your checkDataBase method, you're not opening the same database you are creating in DatabaseEvent. Instead call:
DatabaseEvent db = new DatabaseEvent(context);
db.getReadableDatabase();

Storm Crashing after 23 hours

Hello all I have a basic Storm application set up where it receives a stream of tweets and stores them in a MySQL database. The application works great for the first ~23 hours or so then it starts giving the following error:
SQL Exception
SQL State: 08003
After it does this a few times it dies. I'm using the standard JBDC connector to connect to the database from Java. The code for the functions for storing and setting up the DB connection are as follows:
private String _db="";
private Connection conn = null;
private PreparedStatement pst = null;
public ArchiveBolt(String db){
_db = db;
}
private void setupConnection() {
//Connect to the database
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:8889/twitter_recording", "root", "root");
} catch (Exception e){
e.printStackTrace();
}
}
public void execute(Tuple tuple, BasicOutputCollector collector) {
Status s = (Status) tuple.getValue(0);
//setup the connection on the first run through or if the connection got closed down
try {
setupConnection();
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.toString());
}
try {
pst = conn.prepareStatement("INSERT INTO " + _db + " (tweet)" +
"VALUES (?);");
pst.setString(1, s.toString());
//execute the SQL
pst.executeUpdate();
} catch (SQLException ex) {
// handle any errors
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
if(ex.getSQLState().equals("08003")){
setupConnection();
}
} finally {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
After it became apparent that it was crashing because of a 08003 error I decided that if it threw that error it should retry the set up of the connection, however that didn't help either. Could anyone point me in the right direction for solving this issue?
After it became apparent that it was crashing because of a 08003 error I decided that if it threw that error it should retry the set up of the connection, however that didn't help either. Could anyone point me in the right direction for solving this issue?
There are basically two problems here that need to be solved:
Why are the connections getting lost in the first place?
Why isn't your attempt to reconnect succeeding?
For the first problem, you should take a look at the MySQL logs to see if there are any indications there. And also, check for SQL exceptions immediately prior to the (repeated) "state 080003" exceptions. The latter are simply telling you that the connection has died previously.
My guess is that the problem is one of the following:
The MySQL server has timed out the connection due to inactivity. You can change the connection timeout in the MySQL configs if this is the problem.
Your application may be slowly leaking JDBC connections.
For the second problem, the general approach is correct, but your code doesn't match the description. In fact, it looks like it is always trying to establish a new database connection each time your execute method is called. This renders the reconnection call in your exception handler pointless. (OTOH, the code show signs that someone has been "beating on it" to try to get it to work ... and that could well be part of the problem.)
I would check that setupConnection is being called when it needs to be, and look for any exception that might be thrown. In addition, you should make sure that you explicitly close() the dead connection object ... and rethink / recode your connection management so that it doesn't leak.
For the record, there is a connection URL parameter called "autoReconnect" that in the distant past used to "deal" with lost connections. Unfortunately, the original implementation was unsafe, so they effectively disabled it; see this Question for details: Why does autoReconnect=true not seem to work?

Categories