Android Studio - Neo4j Connection

I wanna develop Android project with Neo4j Database in Android Studio. How can I do this? I tried Neo4j driver but it didn't work. Can you help me please?

what driver did you try and what happened?

I tried neo4j driver, I wrote the code, but it didn't register in the database. I got an application stopped error in android studio.

This code:
private void addPerson(String companyname, String companymail, String companypassword,String companypasswordagain) {

    Session session = driver.session();
    try {
        driver = GraphDatabase.driver("bolt://localhost:7474", AuthTokens.basic("neo4j", "password"));
        Query query = new Query("CREATE (s:Company{cname:$companyname,cmail:$companymail,pass:$companypassword,passagain:$companypasswordagain})", parameters("companyname", companyname, "companymail", companymail, "companypassword", companypassword, "companypasswordagain", companypasswordagain));
        session.run(query);

    } catch (Exception e) {
         Log.d("NEO4J","addPerson: ",e);
    }finally{
        if(driver != null){
            driver.close();
        }
    }
}

I added this dependency in gradle: api('org.neo4j.driver:neo4j-java-driver:4.4.11') and I used jdk 11
I guess my code is wrong. I don't know.

There a few points to make about the code:

  1. You should get your session within the try-with-resources block, so it is auto closed.
  2. You are using a driver on the first line, but then getting a new driver in the try block. Is the first driver an instance variable?
  3. You should create one driver at start up and use it throughout the life of the application, thus you don't close it as well. This is because it's a heavy resource to create. The session is what you want to create for each use.
  4. Using 'session.run' is ok for prototyping and unit tests, but you should use transaction functions for production code. They have built-in retry logic and you can execute many queries within the one transaction, which is useful if you have complex processing that is requires several queries.
  5. What is Log.d()?

I don't use the Query object, but your use looks fine. Try this, and let me know if it doesn't work.


    try(Session session = driver.session()) {
        Query query = new Query("CREATE (s:Company{cname:$companyname,cmail:$companymail,pass:$companypassword,passagain:$companypasswordagain})", parameters("companyname", companyname, "companymail", companymail, "companypassword", companypassword, "companypasswordagain", companypasswordagain));
        session.run(query);

    } catch (Exception e) {
         Log.d("NEO4J","addPerson: ",e);
    }

Thanks for your answer
private Driver driver; I had defined the driver object outside the function
And then;
I updated the code;

try (Session session = driver.session()) {
    driver = GraphDatabase.driver("bolt://localhost:7474", AuthTokens.basic("neo4j", "password"));
    Query query = new Query("CREATE (s:Company{cname:$companyname,cmail:$companymail,pass:$companypassword,passagain:$companypasswordagain})", parameters("companyname", companyname, "companymail", companymail, "companypassword", companypassword, "companypasswordagain", companypasswordagain));
    session.run(query);

} catch (Exception e) {
     
}

I didn't get error but it didn't register in the database.

By the way that is where I run the function;

new Thread(new Runnable() {
@Override
public void run() {
addPerson(companyname,companymail,companypassword,companypasswordagain);
}
}).start();

Where am I doing it wrong?

Can you share the code where you define the driver?

As I stated earlier, you don’t need the second line where you create a new driver, which isn’t used. Also, you want to create one driver when your application starts and use it throughout your code.

The thread code looks fine, but maybe avoid it until you get your method working.

What do you mean by ‘it’s didn’t register‘?

Are you running an instance of the database locally or on a server?

I am running an instance of database on a server.
The whole code is here:

private Button register;
private EditText txtcname;
private EditText txtcmail;
private EditText txtcpassword;
private EditText txtcpasswordagain;
private Driver driver;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_register);
    register =  findViewById(R.id.koi_button);
    txtcname = findViewById(R.id.koi_cname);
    txtcmail= findViewById(R.id.koi_mail);
    txtcpassword= findViewById(R.id.koi_password);
    txtcpasswordagain=  findViewById(R.id.koi_passwordagain);



    register.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            String companyname=txtcname.getText().toString();
            String companymail=txtcmail.getText().toString();
            String companypassword=txtcpassword.getText().toString();
            String companypasswordagain=txtcpasswordagain.getText().toString();



            new Thread(new Runnable() {
                @Override
                public void run() {

               addPerson(companyname,companymail,companypassword,companypasswordagain);
                }
            }).start();


            startActivity(new Intent(Register.this,Profile.class));


        }
    });
}

private void addPerson(String companyname, String companymail, String companypassword,String companypasswordagain) {

  
    try (Session session = driver.session()){

        driver = GraphDatabase.driver("bolt://localhost:7474", AuthTokens.basic("neo4j", "password"));
Query query = new Query("CREATE (s:Company{cname:$companyname,cmail:$companymail,pass:$companypassword,passagain:$companypasswordagain})", parameters("companyname", companyname, "companymail", companymail, "companypassword", companypassword, "companypasswordagain", companypasswordagain));
session.run(query);
        });


    }catch(Exception e){

    }finally{
        if(driver != null){
            driver.close();
        }
    }
}

I think if you run this code as is, you will get a null pointer exception when calling addPerson. This is because you are assigning 'driver' after is use in the try-with-resources's resource creation. You don't see the null pointer because you catch block eats the exception and the finally block will not throw an exception since driver is null (driver.close() does not get called). You can verify this by logging or printing something in your catch block.

Assuming the above is true, you need to move the driver assignment before the session assignment. This is ok for getting things working, but it is not a good approach for an actual application. You want to create the driver once at application startup and inject it into classes that need it. Are you using dependency injection? I am not an android developer, but I read about Hilt on the developer website. You should look into using it. Dependency injection makes complex systems more manageable.

You don't want to create a new driver each time you need it is because it is a heavy process. It creates a connection pool that is intended to be shared throughout your application. A session, on the other hand, is intended to be used once and discarded.

Have you tried connecting to your server using Neo4j's browser in Neo4j Desktop to make sure it is working? You can use the cypher-shell CLI tool as well.