Categories
discuss

How to know if a method is thread safe

Suppose I have a method that checks for a id in the db and if the id doesn’t exit then inserts a value with that id. How do I know if this is thread safe and how do I ensure that its thread safe. Are there any general rules that I can use to ensure that it doesn’t contain race conditions and is generally thread safe.

public TestEntity save(TestEntity entity) {
       if (entity.getId() == null) {
            entity.setId(UUID.randomUUID().toString());
        }
        Map<String, TestEntity > map = dbConnection.getMap(DB_NAME);
        map.put(entity.getId(), entity);
        return map.get(entity.getId());
}

Answer

This is a how long is a piece of string question…

A method will be thread safe if it uses the synchronized keyword in its declaration.

However, even if your setId and getId methods used synchronized keyword, your process of setting the id (if it has not been previously initialized) above is not. .. but even then there is an “it depends” aspect to the question. If it is impossible for two threads to ever get the same object with an uninitialised id then you are thread safe because you would never be attempting to concurrently modifying the id.

It is entirely possible, given the code in your question, that there could be two calls to the thread safe getid at the same time for the same object. One by one they get the return value (null) and immediately get pre-empted to let the other thread run. This means both will then run the thread safe setId method – again one by one.

You could declare the whole save method as synchronized, but if you do that the entire method will be single threaded which defeats the purpose of using threads in the first place. You tend to want to minimize the synchronized code to the bare minimum to maximize concurrency.

You could also put a synchronized block around the critical if statement and minimise the single threaded part of the processing, but then you would also need to be careful if there were other parts of the code that might also set the Id if it wasn’t previously initialized.

Another possibility which has various pros and cons is to put the initialization of the Id into the get method and make that method synchronized, or simply assign the Id when the object is created in the constructor.

I hope this helps…

Edit… The above talks about java language features. A few people mentioned facilities in the java class libraries (e.g. java.util.concurrent) which also provide support for concurrency. So that is a good add on, but there are also whole packages which address the concurrency and other related parallel programming paradigms (e.g. parallelism) in various ways.

To complete the list I would add tools such as Akka and Cats-effect (concurrency) and more.

Not to mention the books and courses devoted to the subject.

I just reread your question and noted that you are asking about databases. Again the answer is it depends. Rdbms’ usually let you do this type of operation with record locks usually in a transaction. Some (like teradata) use special clauses such as locking row for write select * from some table where pi_cols = 'somevalues' which locks the rowhash to you until you update it or certain other conditions. This is known as pessimistic locking.

Others (notebly nosql) have optimistic locking. This is when you read the record (like you are implying with getid) there is no opportunity to lock the record. Then you do a conditional update. The conditional update is sort of like this: write the id as x provided that when you try to do so the Id is still null (or whatever the value was when you checked). These types of operations are usually down through an API.

You can also do optimistics locking in an RDBMs as follows: SQL Update tbl Set x = 'some value', Last_update_timestamp = current_timestamp() Where x = bull AND last_update_timestamp = 'same value as when I last checked' In this example the second part of the where clause is the critical bit which basically says “only update the record if no one else did and I trust that everyone else will update the last update to when they do”. The “trust” bit can sometimes be replaced by triggers.

These types of database operations (if available) are guaranteed by the database engine to be “thread safe”.

Which loops me back to the “how long is a piece of string” observation at the beginning of this answer…

Categories
discuss

drawableStart in button doesn’t scale correctly

I have a drawableStart icon drawable in my Button below but it doesn’t scale correctly. What can i do to correct this?

<Button
    android:id="@+id/show_in_map_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="8dp"
    android:layout_marginTop="32dp"
    android:layout_marginEnd="8dp"
    android:background="@drawable/round_details_button"
    android:drawableStart="@drawable/location_btn"
    android:drawableTint="@android:color/white"
    android:fontFamily="@font/montserrat_medium"
    android:paddingStart="15dp"
    android:paddingEnd="15dp"
    android:text="@string/show_in_map_button"
    android:textColor="@android:color/white"
    android:textSize="14sp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/place_description" />

P.S: I’ve seen a few posts regarding this issue that attempted to solve it in code using ScaleDrawable, but that didn’t work for me.

result

Answer

There is an old approach that works for me.

I simply create bounds and set it to my button. This way any drawable I attach to my drawable takes the dimension of the bounds.

drawable.bounds = Rect(0, 0, 80, 80) // in this case, the drawable is going to be 80 x 80
button.setCompoundDrawables(drawable, null, null, null)

I hope this helps. Merry coding!

Categories
discuss

Weird bug in Javascript splice method

I have an array which contains “Zeros” and I want to move all of the “Zeros” to the last indexes of the array.

The expected output is:

[1,2,3,0,0,0,0]

But instead I get:

[1,2,0,3,0,0,0]

let a = [0, 1, 2, 0, 0, 3, 0];
let count = 0;
let len = a.length;

for (i = 0; i < len; i++) {
  if (a[i] == 0) {
    count = count + 1;
    a.splice(i, 1);
  }
}

for (j = 0; j < count; j++) {
  a.push(0);
}

console.log(a);

Answer

Because splice changes the length of the array, you could iterate from the end of the array and splice the found value directly to the last index.

With this approach, you need only a single loop.

var a = [0, 1, 2, 0, 0, 3, 0],
    i = a.length;

while (i--) {
    if (a[i] === 0) {
        a.splice(a.length, 0, ...a.splice(i, 1));
    }
}

console.log(a);

A shorter approach without splicing – and starting from zero.

var a = [0, 1, 2, 0, 0, 3, 0],
    i, j = 0;

for (i = 0; i < a.length; i++) {
    if (a[i] !== 0) {
        [a[j], a[i]] = [a[i], a[j]]; // swap
        j++;
    }        
}

console.log(a);
Categories
discuss

How do Decompress image using BASE64 in android studio

I created String from ByteMap

 public String StringImage(Bitmap bitmap) {

    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);

    byte[] imageByteArray = byteArrayOutputStream.toByteArray();
    String encodeImage = Base64.encodeToString(imageByteArray, Base64.DEFAULT);

    return encodeImage;
}

and I placed this on sql server.

Downloading this from sql server is not a problem. After download I want to create ByteMap from this string. It means I need decode that string and create BitMap, but that is too hard for me.

Here I am trying decode string and create bitmap

String donwloadImage = jsonObject.getString("image");
String encode = Base64.encodeToString(donwloadImage.getBytes(),Base64.DEFAULT);
byte [] bytes = Base64.decode(encode, Base64.DEFAULT);
Bitmap  bitmap= BitmapFactory.decodeByteArray(bytes,0,bytes.length);

Answer

Convert Base64 String to Bitmap like this –

 byte[] decodeByte = Base64.decode(encodeImage, Base64.DEFAULT);
 Bitmap decodedBitmap = BitmapFactory.decodeByteArray(decodeByte, 0, decodeByte.length);
Categories
discuss

Your application has authenticated using end user credentials from the Google Cloud SDK which are not supported by the translate.googleapis.com

After reading similar questions, such as:

i am using gcp service account but when calling dialogue flow api its giving error :

and

Why is Google Cloud API trying to connect as an end-user?

and applying the suggested solutions I am still getting the error:

    Caused by: com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
  "code" : 403,
  "errors" : [ {
    "domain" : "usageLimits",
    "message" : "Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the translate.googleapis.com. We recommend that most server applications use service accounts instead. For more information about service accounts and how to use them in your application, see https://cloud.google.com/docs/authentication/.",
    "reason" : "rateLimitExceeded"
  } ],
  "message" : "Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the translate.googleapis.com. We recommend that most server applications use service accounts instead. For more information about service accounts and how to use them in your application, see https://cloud.google.com/docs/authentication/.",
  "status" : "PERMISSION_DENIED"

My pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>seller</groupId>
    <artifactId>home.digest</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>home.digest Maven Webapp</name>
    <!-- FIXME change it to the project's website -->
    <url>http://maven.apache.org</url>
    <repositories>
        <repository>
            <id>prime-repo</id>
            <name>Prime Repo</name>
            <url>http://repository.primefaces.org</url>
        </repository>
    </repositories>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>3.141.59</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.4.10</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.primefaces</groupId>
            <artifactId>primefaces</artifactId>
            <version>6.2</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.logging</groupId>
            <artifactId>jboss-logging</artifactId>
            <version>3.0.1.GA</version>
            <scope>compile</scope>
            <optional>true</optional>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.hibernate.javax.persistence/hibernate-jpa-2.1-api -->
        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.1-api</artifactId>
            <version>1.0.2.Final</version>
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.3.6.Final</version>
             <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.enterprise/cdi-api -->
        <dependency>
            <groupId>javax.enterprise</groupId>
            <artifactId>cdi-api</artifactId>
            <version>2.0.SP1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.as</groupId>
            <artifactId>jboss-as-web</artifactId>
            <version>7.1.1.Final</version>
            <scope>compile</scope>
            <optional>true</optional>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.jboss.spec.javax.ejb/jboss-ejb-api_3.2_spec -->
        <dependency>
            <groupId>org.jboss.spec.javax.ejb</groupId>
            <artifactId>jboss-ejb-api_3.2_spec</artifactId>
            <version>1.0.2.Final</version>
            <scope>provided</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.google.cloud/google-cloud-translate -->
        <dependency>
            <groupId>com.google.cloud</groupId>
            <artifactId>google-cloud-translate</artifactId>
            <version>1.79.0</version>
        </dependency>
        <dependency>
            <!-- jsoup HTML parser library @ https://jsoup.org/ -->
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.11.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.8.1</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>home.digest</finalName>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven 
                defaults (may be moved to parent pom) -->
            <plugins>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>3.2.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

My code:

com.google.cloud.translate.Translate translate = TranslateOptions.getDefaultInstance().getService();
        String translatexText = "EMPTY";
        try {
            Translation translation = translate.translate("Guten Tag", Translate.TranslateOption.sourceLanguage("de"),
                    Translate.TranslateOption.targetLanguage("bg"),
                    // Use "base" for standard edition, "nmt" for the
                    // premium model.
                    Translate.TranslateOption.model("nmt"));

            translatexText = translation.getTranslatedText();
        } catch (Exception e) {
            Logger.getLogger(TestServlet.class).error(e.getMessage(), e);
        }

        System.out.println(translatexText);

Answer

This error message is caused by using User Credentials when you setup the Cloud SDK. Typically this is done using the command gcloud auth login.

There are several methods to solve this problem. Each method uses a Service Account.

Method 1:

Create a service account and set up the Cloud SDK to use the service account.

Example command:

gcloud auth activate-service-account test@development-123456.iam.gserviceaccount.com --key-file=/fullpath/service-account.json

Method 2:

Set the environment variable GOOGLE_APPLICATION_CREDENTIALS to point to your service account JSON file.

set GOOGLE_APPLICATION_CREDENTIALS=/fullpath/service-account.json

Method 3:

Specify the service account when creating your Java SDK clients.

This link shows examples of specifying a service account file:

Setting Up Authentication for Server to Server Production Applications

Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..