Iterating on a map from Guava Cache loses data

I started benchmarking ways to find key by value in Guava cache and I noticed strange behaviour related to concurrency level. I’m not sure if that’s a bug or undefined behaviour or maybe even expected but not specified.

My benchmark is supposed to find key by value in Guava Cache, not an usual thing to do, I know.

That’s my complete benchmark class:

@Fork(4)
@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@Warmup(iterations = 1, time = 100, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 4, time = 100, timeUnit = TimeUnit.MILLISECONDS)
public class ValueByKey {

    private Long counter = 0L;

    private final int MAX = 2500;

    private final LoadingCache<String, Long> stringToLong = CacheBuilder.newBuilder()
        .concurrencyLevel(1)
        .maximumSize(MAX + 5)
        .build(new CacheLoader<String, Long>() {
            public Long load(String mString) {
                return generateIdByString(mString);
            }
        });

    private final Map<String, Long> mHashMap = new Hashtable<>(MAX);

    @Setup(Level.Trial)
    public void setup() {
        // Populate guava cache
        for(int i = 0; i <= MAX; i++) {
            try {
                stringToLong.get(UUID.randomUUID().toString());
            } catch (ExecutionException e) {
                e.printStackTrace();
                System.exit(1);
            }
        }
    }

    @Benchmark
    public String stringToIdByIteration() {
        Long randomNum = ThreadLocalRandom.current().nextLong(1L, MAX);

        for(Map.Entry<String, Long> entry : stringToLong.asMap().entrySet()) {
            if(Objects.equals(randomNum, entry.getValue())) {
                return entry.getKey();
            }
        }
        System.out.println("Returning null as value not found " + randomNum);
        return null;
    }

    @Benchmark
    public String stringToIdByIterationHashTable() {
        Long randomNum = ThreadLocalRandom.current().nextLong(1L, MAX);

        for(Map.Entry<String, Long> entry : mHashMap.entrySet()) {
            if(Objects.equals(randomNum, entry.getValue())) {
                return entry.getKey();
            }
        }
        System.out.println("Returning null as value not found " + randomNum);
        return null;
    }

    private Long generateIdByString(final String mString) {
        mHashMap.put(mString, counter++);
        return counter;
    }

}

What I noticed is when I change .concurrencyLevel(1) to number different than 1 I’m starting to lose data. The following output is from concurrency level 4:

Iteration   1: Returning null as value not found 107
Returning null as value not found 43
Returning null as value not found 20
Returning null as value not found 77
Returning null as value not found 127
Returning null as value not found 35
Returning null as value not found 83
Returning null as value not found 43
Returning null as value not found 127
Returning null as value not found 107
Returning null as value not found 83
Returning null as value not found 82
Returning null as value not found 40
Returning null as value not found 58
Returning null as value not found 127
Returning null as value not found 114
Returning null as value not found 119
Returning null as value not found 43
Returning null as value not found 114
Returning null as value not found 18
Returning null as value not found 58
66.778 us/op

I noticed I never lose any data when using HashMap or HashTable for using the same code, it also performs much better:


Benchmark Mode Cnt Score Error Units
ValueByKey.stringToIdByIteration avgt 16 54.639 ± 7.695 us/op
ValueByKey.stringToIdByIterationHashTable avgt 16 11.014 ± 0.516 us/op

Is my code wrong or is that Guava can’t properly handle partitioned HashTable with concurrency level higher than 1?

  • The concurrency level option is used to partition the table internally such that updates can occur without contention.
  • The ideal setting would be the maximum number of threads that could potentially access the cache at one time.

Creating a queue that operates a job

I want to build a thread listens a queue and perform a job whenever i add a item to queue.

But i don’t much idea about how to develop it. I have already tried some Flowable examples from RxJava2 but not recognized how to do it.

I am open for all examples in Android and Java, Maybe message handler or executors would be an easy solution. Sadly no know-how. Esspecally RxJava2 would be great.

keeping same chunk size for all jobs in Spring Batch Application

Just wondering whether its a good practice to keep chunk sizes same for all jobs in a Spring Batch application or should we keep it different for different jobs, depending on the specific job’s behaviour.

I can understand that obviously the answer depends upon a lot of factors, but just wanted to know whats the standard approach for this, if any.

Thanks

How do I compare strings in Java?

I’ve been using the == operator in my program to compare all my strings so far.
However, I ran into a bug, changed one of them into .equals() instead, and it fixed the bug.

Is == bad? When should it and should it not be used? What’s the difference?

PoolingHttpClientConnectionManager vs ClientBuilder

I have currently been using ClientBuilder, but I am wondering if perhaps I should switch over to a PoolingHttpClientConnectionManager (or something else for that matter).

So I am wondering what are the pros and cons of using PoolingHttpClientConnectionManager vs a simple ClientBuilder to get a client.

If at all relevant I am using some internal wildfly implementation of the ClientBuilder.

Optional dependency using modular programming in Java 9 not working with provided module path

I have written source codes of two modules in the directory ~/Desktop/src

code of the module myModuleA

M1.java

package myPack1;
import myPack2.M2;
public class M1
{   
   public static void main(String[] args)   
   {    
     System.out.println("I am M1"); 
     M2.print(); 
     System.out.println("I am M1 Again");
   }
}

module-info.java

module myModuleA
{
      requires myModuleB;
}

code of the module myModuleB

M2.java

package myPack2;
public class M2
{   
   public static void print()   
   {    
     System.out.println("I am M2"); 
   }
}

module-info.java

module myModuleB
{
      exports myPack2;
}

I compiled both modules as:

gyan@#ns:~/Desktop$ javac --module-source-path src -d out -m myModuleA,myModuleB

The directory out is created on the Desktop, which is my current directory.

Thereafter I created another directory on the Desktop with name OtherModule. Cut and paste the compile module directory of myModuleB from the directory out to the directory OtherModule. Deleted the source directory of the module myModuleB from the directory src. Deleted the directory out.

Again I compiled the module myModuleA with the compiled code of the module myModuleB as:

gyan@#ns:~/Desktop$ javac --module-source-path src --module-path OtherModule -d out -m myModuleA

And executed the code successfully as:

gyan@#ns:~/Desktop$ java --upgrade-module-path out/:OtherModule/ -m myModuleA/myPack1.M1
I am M1
I am M2
I am M1 Again
gyan@#ns:~/Desktop$ 

But then I changed the module-info.java file of the module myModuleA as:

module myModuleA
{
    requires static myModuleB;
}

Again I deleted the directory out and compiled the code as:

gyan@#ns:~/Desktop$ javac --module-source-path src --module-path OtherModule -d out -m myModuleA

The code compiles successfully. Then I tried to execute the code as:

gyan@#ns:~/Desktop$ java --upgrade-module-path out/:OtherModule/ -m myModuleA/myPack1.M1
I am M1
Exception in thread "main" java.lang.NoClassDefFoundError: myPack2/M2
    at myModuleA/myPack1.M1.main(M1.java:8)
Caused by: java.lang.ClassNotFoundException: myPack2.M2
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496)
    ... 1 more
gyan@#ns:~/Desktop$ 

What is the reason behind this error, even if I am providing the path to the both compiled modules.

Error pages in Java Spring

My code used to work back when I didnt use Spring. Now that I’m using it doesn’t work. I’m still getting the usual not found page

Web.xml

<!--Error pages-->
<error-page>
    <!-- Missing resource -->
    <error-code>404</error-code>
    <location>/error404</location>
</error-page>
<error-page>
    <!-- Uncaught exception -->
    <error-code>500</error-code>
    <location>/error500</location>
</error-page>

Controller

  //Error pages
@RequestMapping("/error404")
public ModelAndView error404() {
    return new ModelAndView("error404");
}

@RequestMapping("/error500")
public ModelAndView error500() {
    return new ModelAndView("error500");
}

Insertion the data in MySql along with Sqlite database in android

Want to insert and fetch data with SQLite and MySQL in android.To make it clear, I am using two different classes one is MainActivity.java and second is MyDatabaseHelper.java but when I create the object of MyDatabaseHelper.java inside the MainActivity.java class, it’s getting crashed. Thanks in advance!

MainActivity.java

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
    TextView textView;
    EditText editText;
    private static final String 
    DB_URL="jdbc:mysql://192.168.0.101/employee";
    private static final String USER="admin";
    private static final String PASS="root";
    List<String> itemList=new ArrayList<String>();
    MyDatabaseHelper mydb;
    SQLiteDatabase sqLiteDatabase;
    ContentValues values=new ContentValues();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView=(TextView)findViewById(R.id.textView);
        editText=(EditText)findViewById(R.id.editText1);
    }
    protected void onStart() {
        super.onStart();
    }
    public void btnConn(View view)
    {
        String text=editText.getText().toString();
        mydb=new MyDatabaseHelper(getApplicationContext(),"emp_sqlite",null,1);
        boolean result=mydb.addName(text);
        if (result==true)
        {
            Toast.makeText(getApplicationContext(),"Inserted to Sqlite",Toast.LENGTH_LONG).show();
        }
        else
        {
            Toast.makeText(getApplicationContext(),"Not Inserted ",Toast.LENGTH_LONG).show();
        }
        Send objSend=new Send();
        objSend.execute("");
    }
    public void btnShow(View view)
    {
        Fetch objFetch=new Fetch();
        objFetch.execute("");
    }
    private class Send extends AsyncTask<String, String, String>
    {
        String msg="";
        String text=editText.getText().toString();
        protected void onPreExecute()
        {
            textView.setText("Please Wait Inserting Data...");

        }
        protected String doInBackground(String...Strings)
        {
            try
            {
                Class.forName("com.mysql.jdbc.Driver");
                Connection conn= DriverManager.getConnection(DB_URL,USER,PASS);
                if(conn==null)
                {
                    msg="Connection goes wrong";
                }
                else
                {
                    String query="INSERT INTO emp(name) VALUES('"+text+"')";
                    Statement stmt=conn.createStatement();
                    stmt.executeUpdate(query);
                    msg="Insertion Successful to MySql !!!";
                    editText.setText("");

                }
                conn.close();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            return msg;
        }
        protected void onPostExecute(String text)
        {
            Toast.makeText(getApplicationContext(),msg,Toast.LENGTH_LONG).show();
        }
    }
    private class Fetch extends AsyncTask<String, String, String>
    {
        String msg="";
        String result="";
        protected void onPreExecute()
        {
            textView.setText("Please Wait Data...");
        }
        protected String doInBackground(String...Strings)
        {
            try
            {
                Class.forName("com.mysql.jdbc.Driver");
                Connection conn= DriverManager.getConnection(DB_URL,USER,PASS);
                if(conn==null)
                {
                    msg="Connection goes wrong";
                }
                else
                {
                    Statement stmt=conn.createStatement();
                    String query_Result="select * from emp";
                    ResultSet rs = stmt.executeQuery(query_Result);
                    while (rs.next())
                    {
                        result=rs.getString(1);
                        Log.d("Name ",result);
                        itemList.add(result);
                    }
                }
                conn.close();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            return String.valueOf(itemList);
        }
        protected void onPostExecute(String msg)
        {
            Toast.makeText(getApplicationContext(),String.valueOf(itemList),Toast.LENGTH_LONG).show();
            itemList.clear();

        }
    }
   public void btnGetDataFromSqlite(View view) {
        Cursor res = mydb.getAllData();
        if (res.getCount() == 0) {
            //message
            Toast.makeText(MainActivity.this, "Nothing found", Toast.LENGTH_LONG).show();
            return;
        }
        StringBuffer buffer = new StringBuffer();
        while (res.moveToNext()) {
            buffer.append("Id: " + res.getString(0) + "n");
            buffer.append("Name: " + res.getString(1) + "n");
            Toast.makeText(MainActivity.this, buffer.toString(), Toast.LENGTH_LONG).show();
        }
    }
}

MyDatabaseHelper.java

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;     
public class MyDatabaseHelper extends SQLiteOpenHelper {
    private static final int database_version=1;
    private static final String database_name="mysqlite";
    private static final String table_name="emp_sqlite";
    private static final String key_name="name";

    public MyDatabaseHelper(Context applicationContext, String emp_sqlite, Context context, int i) {
        super(context, database_name, null, database_version);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL("create table emp_sqlite(id integer primary key,name text)");

    }
    public boolean addName(String name) {
        SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put(key_name, name);
        sqLiteDatabase.insert(table_name, null, contentValues);
        sqLiteDatabase.close();
        return true;
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        sqLiteDatabase.execSQL("drop table if EXISTS "+table_name);
        onCreate(sqLiteDatabase);

    }
    public int updateName(String oldName , String newName) {
        int count = 0;
        try {
            SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
            ContentValues contentValues = new ContentValues();
            contentValues.put(key_name, newName);
            String[] whereArgs = new String[]{oldName};
            count = sqLiteDatabase.update(table_name, contentValues, key_name + " = ?", whereArgs);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return count;
    }
    public int delete(String uname){
        SQLiteDatabase sqLiteDatabase=this.getWritableDatabase();
        String[] whereArg=new String[]{uname};
        int count=sqLiteDatabase.delete(table_name,key_name+" =?",whereArg);
        return count;
    }
    public Cursor getAllData()
    {
        SQLiteDatabase db=this.getWritableDatabase();
        Cursor res=db.rawQuery("select * from "+table_name,null);
        return res;
    }
}