1

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

Community
  • 1
  • 1
Edmundo Del Gusto
  • 378
  • 1
  • 4
  • 15

1 Answers1

0

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:

  • db connections are usually limited and using them for each application instance will make the db instance going out of available connections quickly, especially if the db interactions aren't really short and if the connections aren't correctly released
  • network connection of a portable device isn't stable and you could lose your connection while running db operations

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.

v.bontempi
  • 1,562
  • 1
  • 9
  • 10
  • first of all.. thank you .. okay I still don't know how to fix this, but your advice with the webservice makes this a little bit irrelevant. I thought jdbc would be kind of a second way to make db-operations. As i expect to have quite a lot of devices communicating to this db I'm going to look forward to get some webservice-skills.. html & javascript would be some keywords for this? ... – Edmundo Del Gusto Feb 17 '16 at 09:34
  • Not strictly required You could develop a RESTful webservice working like an interface to your DB instance using a framework like Spring (on Java) or CakePHP/Zend/Laravel (on PHP) or one of the several MVC frameworks available for nodejs (http://nodeframework.com/) using Javascript And you could run this webservice directly on Bluemix using the runtimes available, so you could take advantage of the integration available on Bluemix between runtimes and SQLDB service – v.bontempi Feb 17 '16 at 10:06
  • thank you, this helps me really a lot.. I just looked into Strongloop and think this is what could be very usefull for my case. I will compare this to Spring and CakePHP. – Edmundo Del Gusto Feb 17 '16 at 11:59