Tuesday, December 31, 2013

Hibernate/grails left join or inner join when using create criteria

Hibernate/grails left join or inner join or join when using create criteria. If you do not use
'CriteriaSpecification.LEFT_JOIN', then it would be a inner join. 
Here is the example as suppose 'User' belongsTo 'Role' which is nullable.
Now you want to left join 'Role' when creating criteria on 'User', then do 
the following. It would take all 'User' row where 'Role' is null or not.
But if you do not use 'CriteriaSpecification.LEFT_JOIN', then it would take only
'User.role' is not null. 


import org.hibernate.criterion.CriteriaSpecification;

List userList = User.createCriteria().list {
    eq("isActive", true);
    createAlias("role", "__role", CriteriaSpecification.LEFT_JOIN)
    eq("__role.someProperty", "some value");
}

Thursday, December 19, 2013

SOAP request in PHP with CURL

Php code to soap action via curl:


<?php
$xml = '<?xml version="1.0" encoding="utf-8"?>'.
    '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'.
    ' xmlns:xsd="http://www.w3.org/2001/XMLSchema"'.
    ' xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">'.
        '<soap:Body>'.
            '<GetShirtInfo xmlns="http://api.soap.website.com/WSDL_SERVICE/">'.
                '<ItemId>15</ItemId>'.
            '</GetShirtInfo>'.
        '</soap:Body>'.
    '</soap:Envelope>';

$url = "https://api.soap.website.com/soap.asmx?wsdl";

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);

$headers = array();
array_push($headers, "Content-Type: text/xml; charset=utf-8");
array_push($headers, "Accept: text/xml");
array_push($headers, "Cache-Control: no-cache");
array_push($headers, "Pragma: no-cache");
array_push($headers, "SOAPAction: http://api.soap.website.com/WSDL_SERVICE/GetShirtInfo");
if($xml != null) {
    curl_setopt($ch, CURLOPT_POSTFIELDS, "$xml");
    array_push($headers, "Content-Length: " . strlen($xml));
}
curl_setopt($ch, CURLOPT_USERPWD, "user_name:password"); /* If required */
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
?>

And output would be like this:


<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
        <ShirtInfoResponse
            xmlns="http://api.soap.website.com/WSDL_SERVICE/">
            <ShirtInfo>
                <ItemId>15</ItemId>
                <ItemName>Some Item Name</ItemName>
                <ItemPrice>658.7</ItemPrice>
                <ItemCurrency>AUD</ItemCurrency>
            </ShirtInfo>
        </ShirtInfoResponse>
    </soap:Body>
</soap:Envelope>

Wednesday, December 18, 2013

Grails withNewSession


Please follow the following scenario:
1. You are saving a domain object 'User'.
2. You are trying to save another domain object 'Activities', indicates that 
   who is saving 'User'.
3. First, 'User' created, so now time to save 'Activities'.
4. But activities failed, what would be the saved user? 'User' would be roll 
   back even if 'Activities' saving between try catch, because of hibernate 
   session?
5. In this scenario you must save your 'Activities' under try catch with 
   'new session', such:

def saveUser = [
    User user = new User(name: "Pritom").save();
    try {
        Activites.withNewSession { sesstion -> 
            new Activities(createdBy: "some name").save();
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

Grails access HttpSession from service or from other src files


import org.springframework.web.context.request.RequestContextHolder; 
HttpSession session = RequestContextHolder.currentRequestAttributes().getSession();

##### 
/* Code */
session.properties.each {
    println it;
}

/* Output from above code */
creationTime=1387331940863
maxInactiveInterval=1800
sessionContext=org.apache.catalina.session.StandardSessionContext@1ff04376
attributeNames=java.util.Collections$2@2aec16fa
class=class org.codehaus.groovy.grails.web.servlet.mvc.GrailsHttpSession
servletContext=org.apache.catalina.core.ApplicationContextFacade@3dc6e9f8
new=false
id=A2791167D1EC3D21025078895357147D
valueNames=[Ljava.lang.String;@71d88d19
lastAccessedTime=1387332146960

#####
/* Code */
session.attributeNames.each {
    println it;
}

/* Output from above code */
SETTING
org.codehaus.groovy.grails.FLASH_SCOPE
USER

#####
/* Code */
session.attributeNames.each {
    println session.getAttribute(it.toString());
}

/* Output from above code */
[paginationCount:10, generateClientID:On]
[:]
[name:Admin, id:1, username:admin, isSystemAdmin:true]

Friday, December 13, 2013

Convert string to ascii and ascii to string using JAVA

Java code to convert string to ascii code and ascii code to string back

Java Regex to convert string to ascii code and ascii code to string back



/**
 *
 * @author Pritom K Mondal
 */
public class AsciiString {
    public static void main(String[] args) {
        String inputString = "Hi, THAI(คุณ), HINDI:(तुम मेरी हो), HANGERIO:(تو مال منی), CHINA:(您), ARBI(أنت), FARSI(شما)";
        System.out.println("ORIGINAL:      " + inputString);
        String encoded = AsciiString.encode(inputString);
        System.out.println("ASCII ENCODED: " + encoded);
        String decoded = AsciiString.decode(encoded);
        System.out.println("ASCII DECODED: " + decoded);
    }
    
    public static String encode(String word) {
        String encoded = "";
        for(Integer index = 0; index < word.length(); index++) {
            int ascii = (int) word.charAt(index);
            Boolean keepAscii = true;
            if(ascii >= 48 && ascii <= 57) {
                keepAscii = false;
            }
            if(ascii >= 65 && ascii <= 90) {
                keepAscii = false;
            }
            if(ascii >= 97 && ascii <= 122) {
                keepAscii = false;
            }
            if(ascii == 32 || ascii == 43 || ascii == 45 || ascii == 46) {
                keepAscii = false;
            }
            if(keepAscii) {
                encoded += "&#" + ascii + ";";
            } else {
                encoded += word.charAt(index);
            }
        }
        return encoded;
    }
    
    public static String decode(String word) {
        String decoded = "";
        for(Integer index = 0; index < word.length(); index++) {
            String charAt = "" + word.charAt(index);
            if(charAt.equals("&") && index < word.length() && ("" + word.charAt(index + 1)).equals("#")) {
                try {
                    Integer length = word.indexOf(";", index);
                    String sub = word.substring(index + 2, length);
                    decoded += Character.toString((char) Integer.parseInt(sub));
                    index = length;
                } catch (Exception ex) {
                    decoded += charAt;
                }
            } else {
                decoded += charAt;
            }
        }
        return decoded;
    }
}

Output for the above program is as following:


ORIGINAL:      Hi, THAI(คุณ), HINDI:(तुम मेरी हो), HANGERIO:(تو مال منی), CHINA:(您), ARBI(أنت), FARSI(شما)
ASCII ENCODED: Hi&#44; THAI&#40;&#3588;&#3640;&#3603;&#41;&#44; HINDI&#58;&#40;&#2340;&#2369;&#2350; &#2350;&#2375;&#2352;&#2368; &#2361;&#2379;&#41;&#44; HANGERIO&#58;&#40;&#1578;&#1608; &#1605;&#1575;&#1604; &#1605;&#1606;&#1740;&#41;&#44; CHINA&#58;&#40;&#24744;&#41;&#44; ARBI&#40;&#1571;&#1606;&#1578;&#41;&#44; FARSI&#40;&#1588;&#1605;&#1575;&#41;
ASCII DECODED: Hi, THAI(คุณ), HINDI:(तुम मेरी हो), HANGERIO:(تو مال منی), CHINA:(您), ARBI(أنت), FARSI(شما)

Now create a html file named 'index.html' such:


<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <title>String and ASCII</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    </head>
    <body>
        <div>ORIGINAL:      Hi, THAI(คุณ), HINDI:(तुम मेरी हो), HANGERIO:(تو مال منی), CHINA:(您), ARBI(أنت), FARSI(شما)</div>
        <div>ASCII ENCODED: Hi&#44; THAI&#40;&#3588;&#3640;&#3603;&#41;&#44; HINDI&#58;&#40;&#2340;&#2369;&#2350; &#2350;&#2375;&#2352;&#2368; &#2361;&#2379;&#41;&#44; HANGERIO&#58;&#40;&#1578;&#1608; &#1605;&#1575;&#1604; &#1605;&#1606;&#1740;&#41;&#44; CHINA&#58;&#40;&#24744;&#41;&#44; ARBI&#40;&#1571;&#1606;&#1578;&#41;&#44; FARSI&#40;&#1588;&#1605;&#1575;&#41;</div>
        <div>ASCII DECODED: Hi, THAI(คุณ), HINDI:(तुम मेरी हो), HANGERIO:(تو مال منی), CHINA:(您), ARBI(أنت), FARSI(شما)</div>
    </body>
</html>

Now showing in browser:


In browser they are appearing same. Such original string, after ascii conversion and the back to again string. So why you convert them?
  • It is easy to maintain them.
  • Easy to insert to and get from database.
  • You have no worry about what characters are you inserting to database.
  • If you create xml from those data, you do not need to worry about what characters support in xml file, specially when you transport data via api server.

Thursday, December 12, 2013

Base64 encode/decode with JAVA

Java code to encode and decode base64


package pritom;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * Created with IntelliJ IDEA.
 * User: pritom
 * Date: 12/12/13
 * Time: 10:41 AM
 * To change this template use File | Settings | File Templates.
 */
public class EncodeDecodeBase64 {
    public static void main(String[] args) throws Exception{
        String baseString = "TESTING BASE 64 ENCODING AND DECODING WITH JAVA";
        System.out.println("Base string:     " + baseString);

        /**
         * Encoding to base 64
         */
        BASE64Encoder base64Encoder = new BASE64Encoder();
        String encodedString = base64Encoder.encodeBuffer(baseString.getBytes());
        System.out.print("Encoded base 64: " + encodedString);

        /**
         * Decoding from base 64
         */
        BASE64Decoder base64Decoder = new BASE64Decoder();
        String decodedString = new String(base64Decoder.decodeBuffer(encodedString), "UTF-8");
        System.out.println("Decoded base 64: " + decodedString);
    }
}

Output


Base string:     TESTING BASE 64 ENCODING AND DECODING WITH JAVA
Encoded base 64: VEVTVElORyBCQVNFIDY0IEVOQ09ESU5HIEFORCBERUNPRElORyBXSVRIIEpBVkE=
Decoded base 64: TESTING BASE 64 ENCODING AND DECODING WITH JAVA

Checking if an element is hidden with jQuery

Html

<form style='display: none'>
<input id='name' type='text' style='display: inline-block' />
</form>

jQuery code


if( $("input#name").is(":visible") ) {
    /* do something, selector is not hidden */
}

This will select the input field and then test correctly whether it is visible in the DOM. This check will make sure all parent elements are visible too, as well as the original CSS display attribute.

Wednesday, December 11, 2013

Change i18n locale from a controller before calling the view


package pritom.com.locale;

import org.springframework.web.servlet.support.RequestContextUtils as RCU

class FormController {
    def test() {
        Locale locale = new Locale("fr");
        RCU.getLocaleResolver(request).setLocale(request, response, locale);
        render g.message(code: "default.paginate.prev");
    }
}

Monday, December 9, 2013

Reading i18n messages from the database with Grails

At first create a model class:


package com.locale.messaging

class Message {
    String code
    Locale locale
    String text

    static constraints = {
        code(unique: ["locale"])
    }

    static mapping = {
        version(false);
    }
}

Then implement a class that extends the org.springframework.context.support.AbstractMessageSource class. In the example below I am using simple GORM finders to lookup a message using the code and locale


package com.locale.messaging

import com.locale.messaging.Message
import net.sf.ehcache.Ehcache
import org.springframework.context.support.AbstractMessageSource
import net.sf.ehcache.Element;
import java.text.MessageFormat

/**
 * Created with IntelliJ IDEA.
 * User: pritom
 * Date: 9/12/13
 * Time: 9:09 AM
 * To change this template use File | Settings | File Templates.
 */
class DatabaseMessageSource extends AbstractMessageSource {
    Ehcache messageCache
    def messageBundleMessageSource

    @Override
    protected MessageFormat resolveCode(String code, Locale locale) {
        def key = "${code}_${locale.language}_${locale.country}_${locale.variant}";
        def format = messageCache.get(key)?.value;
        if (!format) {
            Message message = Message.findByCodeAndLocale(code, locale);
            if (message) {
                format = new MessageFormat(message.text, message.locale);
            } else {
                format = messageBundleMessageSource.resolveCode(code, locale);
            }
            messageCache.put(new Element(key, format))
        } else {
            format = (MessageFormat) format;
        }
        return format;
    }
}

Then configure an appropriate cache bean (I'm using Ehcache) in Spring and wire it into your MessageSource in grails-app/conf/spring/resources.groovy file:

import com.bitmascot.util.DatabaseMessageSource
import org.springframework.cache.ehcache.EhCacheFactoryBean

// Place your Spring DSL code here
beans = {
    messageCache(EhCacheFactoryBean) {
        eternal = false;
        timeToIdle = 5000;
    }
    messageSource(DatabaseMessageSource) {
        messageCache = messageCache
        messageBundleMessageSource = ref("messageBundleMessageSource")
    }

    messageBundleMessageSource(org.codehaus.groovy.grails.context.support.PluginAwareResourceBundleMessageSource) {
        basenames = "grails-app/i18n/messages"
    }
}

http://graemerocher.blogspot.com/2010/04/reading-i18n-messages-from-database.html

Sunday, December 8, 2013

How to Set up a Foreign Key Constraint in MySQL

The following is a simple example that illustrates Foreign Key constraints:

Creating a table for manager:
CREATE TABLE manager (id integer primary key auto_increment, name text) ENGINE=InnoDB;

Creating a table for club and creating a foreign key constraint for manager_id with key 'manager_id_reference':
CREATE TABLE club (id integer primary key auto_increment, is_accessible char, manager_id integer NOT NULL) ENGINE=InnoDB;
ALTER TABLE club ADD CONSTRAINT manager_id_reference FOREIGN KEY(manager_id) REFERENCES manager (id);

Inserting some managers:
INSERT INTO manager(name) VALUES('Pritom');
INSERT INTO manager(name) VALUES('Kumar');

Inserting some clubs:
INSERT INTO club(is_accessible, manager_id) VALUES(true, 1);
INSERT INTO club(is_accessible, manager_id) VALUES(false, 2);

Let see manager table data (SELECT * FROM manager):
ID NAME
1 Pritom
2 Kumar

Let see club table data (SELECT * FROM club):
ID IS_ACCESSIBLE MANAGER_ID
1 1 1
2 0 2
Let see manager table structure (DESCRIBE manager):
FIELD TYPE NULL KEY DEFAULT EXTRA
id int(11) NO PRI (null) auto_increment
name text YES (null)
Let see club table structure (DESCRIBE club):
FIELD TYPE NULL KEY DEFAULT EXTRA
id int(11) NO PRI (null) auto_increment
is_accessible char(1) YES (null)
manager_id int(11) NO MUL (null)

Now try to delete manager:
DELETE FROM USER WHERE id = 1;

will error as:
Schema Creation Failed: Cannot delete or update a parent row: a foreign key constraint fails (`db_2_8d4a1`.`club`, CONSTRAINT `manager_id_reference` FOREIGN KEY (`manager_id`) REFERENCES `manager` (`id`)):

This happens because the data in the manager table depends on the data in the club table.

Full sqlFiddle

Getting Request , Response & ServletContext in the Grails service class

import org.codehaus.groovy.grails.web.util.WebUtils;

Getting current request object:
def request = WebUtils.retrieveGrailsWebRequest().getCurrentRequest();

Getting response object:
def response = WebUtils.retrieveGrailsWebRequest().getCurrentResponse();

Getting servletContext object:
def servletContext = WebUtils.retrieveGrailsWebRequest().getServletContext();

Thursday, December 5, 2013

POSTing json data with php cURL


<?php
$params = array(
    "id" => 1,
    "name" => "Pritom Kumar Mondal"
);
$param = json_encode($params);
$ch   = curl_init("http://localhost/api_server/user");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $param);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-Type: application/json',
    'Content-Length: ' . strlen($param))
);
$response = curl_exec($ch);
print_r($response);
?>

Wednesday, December 4, 2013

mysql date format

The DATE_FORMAT() function is used to display date/time data in different formats.

Syntax

DATE_FORMAT(date,format)
Where date is a valid date and format specifies the output format for the date/time.
The formats that can be used are from http://www.w3schools.com/sql/func_date_format.asp:

Format Description
%aAbbreviated weekday name
%bAbbreviated month name
%cMonth, numeric
%DDay of month with English suffix
%dDay of month, numeric (00-31)
%eDay of month, numeric (0-31)
%fMicroseconds
%HHour (00-23)
%hHour (01-12)
%IHour (01-12)
%iMinutes, numeric (00-59)
%jDay of year (001-366)
%kHour (0-23)
%lHour (1-12)
%MMonth name
%mMonth, numeric (00-12)
%pAM or PM
%rTime, 12-hour (hh:mm:ss AM or PM)
%SSeconds (00-59)
%sSeconds (00-59)
%TTime, 24-hour (hh:mm:ss)
%UWeek (00-53) where Sunday is the first day of week
%uWeek (00-53) where Monday is the first day of week
%VWeek (01-53) where Sunday is the first day of week, used with %X
%vWeek (01-53) where Monday is the first day of week, used with %x
%WWeekday name
%wDay of the week (0=Sunday, 6=Saturday)
%XYear of the week where Sunday is the first day of week, four digits, used with %V
%xYear of the week where Monday is the first day of week, four digits, used with %v
%YYear, four digits
%yYear, two digits

Examples in fiddle:

http://sqlfiddle.com/#!2/ccc08/3
















Tuesday, December 3, 2013

Avoid ConcurrentModificationException when using an Java Iterator

Lets explore this scenario with the following example:
First see two methods and then see last two methods.
For first two methods, used simple arraylist and hashmap, so concurrent exception occurs.
But for the later two methods, used copy on write arraylist and concurrent hashmap, so no problem with the last two methods.

package pritom;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Created with IntelliJ IDEA.
 * User: pritom
 * Date: 3/12/13
 * Time: 4:04 PM
 * To change this template use File | Settings | File Templates.
 */
public class ConcurrentModification {
    public static void main(String[] args) {
        ConcurrentModification.concurrentModificationList();
        ConcurrentModification.concurrentModificationHashMap();
        ConcurrentModification.concurrentModificationConcurrentList();
        ConcurrentModification.concurrentModificationConcurrentHashMap();
    }

    private static void concurrentModificationList() {
        try {
            List<String> myDataList = new ArrayList<String>();
            myDataList.add("1");
            myDataList.add("2");
            myDataList.add("3");
            myDataList.add("4");

            System.out.println("Deleting from List: ");
            for (Iterator it = myDataList.iterator(); it.hasNext();) {
                String myObject = (String) it.next();
                if(myObject.equalsIgnoreCase("2") || myObject.equalsIgnoreCase("4")) {
                    System.out.println("Deleting: " + myObject);
                    myDataList.remove(myObject);
                } else {
                    System.out.println("Not deleting: " + myObject);
                }
            }

            System.out.println("After deleting from List: ");
            for (Iterator it = myDataList.iterator(); it.hasNext();) {
                String myObject = (String) it.next();
                System.out.println("Remaining: " + myObject);
            }
        } catch (Throwable ex) {
            System.out.println("***** Deleting from List error: " + ex.toString() + " *****");
        }
    }

    private static void concurrentModificationHashMap() {
        try {
            Map<String, String> myDataList = new HashMap<String, String>();
            myDataList.put("0", "00");
            myDataList.put("1", "11");
            myDataList.put("2", "22");
            myDataList.put("3", "33");

            System.out.println("\n\nDeleting from Map: ");
            for (Iterator it = myDataList.keySet().iterator(); it.hasNext();) {
                String key = (String) it.next();
                if(key.equalsIgnoreCase("2") || key.equalsIgnoreCase("4")) {
                    System.out.println("Deleting: " + key + " = " + myDataList.get(key));
                    myDataList.remove(key);
                } else {
                    System.out.println("Not deleting: " + key + " = " + myDataList.get(key));
                }
            }

            System.out.println("After deleting from Map: ");
            for (Iterator it = myDataList.keySet().iterator(); it.hasNext();) {
                String key = (String) it.next();
                System.out.println("Remaining: " + key + " = " + myDataList.get(key));
            }
        } catch (Throwable ex) {
            System.out.println("***** Deleting from Map error: " + ex.toString() + " *****\n\n");
        }
    }

    private static void concurrentModificationConcurrentList() {
        try {
            List<String> myDataList = new CopyOnWriteArrayList<String>();
            myDataList.add("1");
            myDataList.add("2");
            myDataList.add("3");
            myDataList.add("4");

            System.out.println("\n\nDeleting from Concurrent List: ");
            for (Iterator it = myDataList.iterator(); it.hasNext();) {
                String myObject = (String) it.next();
                if(myObject.equalsIgnoreCase("2") || myObject.equalsIgnoreCase("4")) {
                    System.out.println("Deleting: " + myObject);
                    myDataList.remove(myObject);
                    myDataList.add("55");
                } else {
                    System.out.println("Not deleting: " + myObject);
                }
            }

            System.out.println("After deleting from Concurrent List: ");
            for (Iterator it = myDataList.iterator(); it.hasNext();) {
                String myObject = (String) it.next();
                System.out.println("Remaining: " + myObject);
            }
        } catch (Throwable ex) {
            System.out.println("***** Deleting from Concurrent List error: " + ex.toString() + " *****");
        }
    }

    private static void concurrentModificationConcurrentHashMap() {
        try {
            Map<String, String> myDataList = new ConcurrentHashMap<String, String>();
            myDataList.put("1", "11");
            myDataList.put("2", "22");
            myDataList.put("3", "33");
            myDataList.put("4", "44");

            System.out.println("\n\nDeleting from Concurrent Map: ");
            for (Iterator it = myDataList.keySet().iterator(); it.hasNext();) {
                String key = (String) it.next();
                if(key.equalsIgnoreCase("2") || key.equalsIgnoreCase("4")) {
                    System.out.println("Deleting: " + key + " = " + myDataList.get(key));
                    myDataList.remove(key);
                    System.out.println("Adding: 5 = 55");
                    myDataList.put("5", "55");
                } else {
                    System.out.println("Not deleting: " + key + " = " + myDataList.get(key));
                }
            }

            System.out.println("After deleting from Concurrent Map: ");
            for (Iterator it = myDataList.keySet().iterator(); it.hasNext();) {
                String key = (String) it.next();
                System.out.println("Remaining: " + key + " = " + myDataList.get(key));
            }
        } catch (Throwable ex) {
            System.out.println("***** Deleting from Concurrent Map error: " + ex.toString() + " *****\n\n");
        }
    }
}

And see the output


Deleting from List: 
Not deleting: 1
Deleting: 2
***** Deleting from List error: java.util.ConcurrentModificationException *****


Deleting from Map: 
Not deleting: 3 = 33
Deleting: 2 = 22
***** Deleting from Map error: java.util.ConcurrentModificationException *****




Deleting from Concurrent List: 
Not deleting: 1
Deleting: 2
Not deleting: 3
Deleting: 4
After deleting from Concurrent List: 
Remaining: 1
Remaining: 3
Remaining: 55
Remaining: 55


Deleting from Concurrent Map: 
Not deleting: 1 = 11
Not deleting: 3 = 33
Deleting: 4 = 44
Adding: 5 = 55
Deleting: 2 = 22
Adding: 5 = 55
After deleting from Concurrent Map: 
Remaining: 1 = 11
Remaining: 5 = 55
Remaining: 3 = 33

To Avoid ConcurrentModificationException in multi-threaded environment (first two methods):
1. You can convert the list to an array and then iterate on the array. This approach works well for small or medium size list but if the list is large then it will affect the performance a lot.
2. You can lock the list while iterating by putting it in a synchronized block. This approach is not recommended because it will cease the benefits of multithreading.
3. If you are using JDK1.5 or higher then you can use ConcurrentHashMap and CopyOnWriteArrayList classes. It is the recommended approach.

From the above example its clear that (last two methods):
1. Concurrent Collection classes can be modified avoiding ConcurrentModificationException.
2. In case of CopyOnWriteArrayList, iterator doesn’t accomodate the changes in the list and works on the original list.
3. In case of ConcurrentHashMap, the behavior is not always the same.