Reputation: 388
First: I have some experience in Java but its my first time creating an Android-App. I am using the Bluemix IoT-Foundation-Service and got a Bluemix-DB2-SQL-Database. (My RasPi2 is collecting some sensor datas, publish them via MQTT and an Application running on bluemix that subscribes to this datas, stores them into the DB2-Database).
Now I want to code an Android app, that connects to my database and do some database-things. I started with an simple app. Just a button that adds something on my DB2-TodoList-Table.
Code:
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import java.sql.*;
public class MainActivity extends AppCompatActivity {
static Connection con;
static Statement stmt;
static Statement stmt1;
static DatabaseMetaData dmd;
private static String user = "user*****";
private static String password = "L***********";
private static String url = "jdbc:db2://*.**.*****:50001/SQLDB";
public void connect(){
java.util.Properties properties = new java.util.Properties();
properties.put("user", user);
properties.put("password", password);
properties.put("sslConnection", "true");
try {
Class.forName("com.ibm.db2.jcc.DB2Driver");
con = DriverManager.getConnection(url, properties);
stmt = con.createStatement();
} catch (ClassNotFoundException e) {
// e.printStackTrace();
} catch (SQLException e) {
// e.printStackTrace();
}
}
public void close() throws SQLException, ClassNotFoundException{
stmt.close();
con.close();
}
public static void addSomethingToMyToDoList(int ID, String something) throws SQLException{
if(con != null)
stmt.executeUpdate("INSERT INTO TODOLIST VALUES (" + ID + " , '" + something +"')");
con.commit();
}
public void addSomethingToDatabase(View v){
connect();
int sampleID = 1233;
try {
addSomethingToMyToDoList(sampleID, "testTest");
close();
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
I drag and dropped the db2jcc.jar into the /app/libs folder and did right-click + Add as library
I use Android Studio
I've read that db2jcc.jar doesn't work with jdk 1.8 thats why I installed jdk 1.7 (Did File->Project Structure -> SDK Location -> changed JDK location to my jdk1.7.0 directory)
the build.gradle file contains:
defaultConfig {
[...]
multiDexEnabled true
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile files('libs/db2jcc.jar')
testCompile 'junit:junit:4.12'
compile 'com.android.support:design:23.1.1'
compile 'com.android.support:multidex:1.0.1'
compile 'com.android.support:appcompat-v7:23.1.1'
}
When I run my Application (on AVD) and click on the Button the my app chrashes an I get this message:
Caused by: java.lang.NoClassDefFoundError: com.ibm.db2.jcc.DB2SimpleDataSource
Full error log:
FATAL EXCEPTION: main Process: com.example.egebert.datanbank, PID: 7125 java.lang.IllegalStateException: Could not execute method for android:onClick at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:275) at android.view.View.performClick(View.java:5198) at android.view.View$PerformClick.run(View.java:21147) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) Caused by: java.lang.reflect.InvocationTargetException at java.lang.reflect.Method.invoke(Native Method) at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:270) at android.view.View.performClick(View.java:5198) at android.view.View$PerformClick.run(View.java:21147) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) Caused by: java.lang.NoClassDefFoundError: com.ibm.db2.jcc.DB2SimpleDataSource at java.lang.Class.classForName(Native Method) at java.lang.Class.forName(Class.java:324) at java.lang.Class.forName(Class.java:285) at com.ibm.db2.jcc.am.GlobalProperties.d(Unknown Source) at com.ibm.db2.jcc.am.GlobalProperties.a(Unknown Source) at com.ibm.db2.jcc.am.GlobalProperties.c(Unknown Source) at com.ibm.db2.jcc.am.GlobalProperties.a(Unknown Source) at com.ibm.db2.jcc.am.hb.j(Unknown Source) at com.ibm.db2.jcc.am.hb.(Unknown Source) at java.lang.Class.classForName(Native Method) at java.lang.Class.forName(Class.java:324) at java.lang.Class.forName(Class.java:285) at com.ibm.db2.jcc.DB2BaseDataSource.class$(Unknown Source) at com.ibm.db2.jcc.DB2BaseDataSource.(Unknown Source) at java.lang.Class.classForName(Native Method) at java.lang.Class.forName(Class.java:324) at java.lang.Class.forName(Class.java:285) at com.ibm.db2.jcc.DB2Driver.class$(Unknown Source) at com.ibm.db2.jcc.DB2Driver.(Unknown Source) at java.lang.Class.classForName(Native Method) at java.lang.Class.forName(Class.java:324) at java.lang.Class.forName(Class.java:285) at com.example.egebert.datanbank.MainActivity.connect(MainActivity.java:40) at com.example.egebert.datanbank.MainActivity.addSomethingToDatabase(MainActivity.java:78) at java.lang.reflect.Method.invoke(Native Method) at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:270) at android.view.View.performClick(View.java:5198) at android.view.View$PerformClick.run(View.java:21147) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
I tried
Class.forName("com.ibm.db2.jcc.DB2Driver").newInstance();
instead of
Class.forName("com.ibm.db2.jcc.DB2Driver");
too.
Is there no way to get the JDBC-db2Driver work on Android? Just found This stackoverflow question telling me, that you can't connect to an bluemix-db2-server using android. Is this right? Or is there a way to fix the NoClassDefFoundError?
THANK YOU
Upvotes: 1
Views: 597
Reputation: 1562
The error is pretty clear, your application cannot find the db2 modules. Check that you are importing correctly these modules into your application library and that the drivers added into lib are providing the classes you are using for datasource.
Anyway I would avoid to make your application to directly connect to an external database for several reasons:
Usually a better solution should be adding an integration layer like a webservice, managing all the db interactions included the db connections, and exposing some endpoints for the application integration.
Upvotes: 0