Friday, July 29, 2022

How to grant privileges Mysql user for remote host machine

In this tutorial, we will learn how to grant privileges MySQL users for remote host/ip_address of the machine

SSH into remote server:

First, let's enter the remote server where the MySQL server is allocated.

ssh server_user_name@server_ip_address

Use your own server_user_name and server_ip_address.

ssh ubuntu@65.110.98.71

Now, logged in as MySQL's root user

mysql -u root_username -p

Enter your root username and hit enter. After that, it will ask for MySQL password use your MySQL password

Grant All Privileges for all host:

GRANT ALL PRIVILEGES ON *.* TO 'mysql_username'@'%' IDENTIFIED BY 'mysql_password';
FLUSH PRIVILEGES;

Here, we are giving the MySQL user access to it from any host or IP address by specifying %. Don't forget to flush privileges after granting privileges to the user.

Grant All Privileges for a host:

If we want to restrict MySQL user from all the hosts and give access to the specific IP address or host machine then we can use the following command

GRANT ALL PRIVILEGES ON *.* TO 'mysql_username'@'ip_address' IDENTIFIED BY 'mysql_password';
FLUSH PRIVILEGES;

Make sure to use your own mysql_username and ip_address to allow access from that host.

Revoke privileges:

REVOKE ALL PRIVILEGES ON *.* FROM 'mysql_username'@'ip_address';
FLUSH PRIVILEGES;

List host users:

SELECT user, host FROM mysql.user;

This will list all the users associated with the hosts.

List all the privileges given to users:

SELECT * FROM information_schema.user_privileges;

This will show all the users with hosts and privileges available for that user and host.

Delete user associated with host:

DROP USER 'mysql_username'@'ip_address';

This will drop the user associated with that IP address and revoke all the privileges.

Share:

Wednesday, July 27, 2022

Install Mysql in Docker on Ubuntu Linux server

In this tutorial, we will learn how to install Mysql on Docker.

Please follow the steps to install docker using this tutorial Install Docker on Ubuntu

Install Mysql using Docker:

For installing the desired version of MySQL first, visit docker mysql image section where we can find the available MySQL version. In this tutorial, we are using MySQL version 5.7.

Use the following command on the server to install the MySQL image

docker pull mysql:5.7 

Use your own version instead of 5.7

This will pull the image and install Mysql inside docker. We can verify the image using the following command

docker images

The output of the above command will be similar to this

mysql          5.7                   314749b3a5c   17 hours ago    431MB

Create Mysql Container:

Let’s create the MySQL container. To create a MySQL container, use the following command.

docker run --name=cn-mysql -d -p 3316:3306 --env="MYSQL_ROOT_PASSWORD=root1249" mysql:5.7

Note: use your own MySQL root password instead of root1249 and the port instead of 3316 and container name instead of cn-mysql

This will create the container. We can see the container using the following command

docker container ls -a 
OR
docker ps -a

Enter into the Mysql server:

If we want to do the regular MySQL operation, then we need to enter the MySQL server inside docker as below

docker exec -it elint-mysql bash

Now login into MySQL using the command

mysql -u root -p

Use your own MySQL password which is used while creating a container i.e root1249

Now we can do operations like creating databases and users.

Creating Mysql User:

In order to create a MySQL user and give permission visit the tutorial, Create Mysql User and Grant Privileges

Let's create a user

create user 'username'@'%' identified by 'password';

Note: change your own username and password. If you need to connect your created user from any client, you should create the user with “%” which signifies, that you can connect this user from any host.

Now, let's grant privileges

grant all privileges on *.* to username;

Use the previously created username

flush privileges;
Share:

Install Docker on Ubuntu 20.04

In this tutorial, we will learn how to install docker on Ubuntu Linux.

Install docker using the repository:

For this, first set up the repository. Use the following command.

sudo apt-get update
sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

Now, add docker's GPG key

sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

Now give the sufficient permission

sudo chmod a+r /etc/apt/keyrings/docker.gpg

In order to set up the repository, use the following command

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Now for installing Docker use the following command, which will install the latest docker.

sudo apt-get update & sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

Install Docker using .deb package:

If we might have a problem with installing the docker with the above or wants to install a specific version of the docker then using .deb package is a good solution.

Download the desired version of .deb from here

In order to test the ubuntu version use the following command

lsb_release -a

we can get the output as below

No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 20.04.3 LTS
Release:	20.04
Codename:	focal

Here, the codename is focal so We chose the same as above. Then browse to pool/stable/, choose amd64, armhf, arm64, or s390x, and download the .deb file

In order to test the CPU available use the following command

lscpu

Go to the download folder and execute the deb package using the following command

sudo dpkg -i docker-ce-cli_18.09.0_3-0_ubuntu-bionic_amd64.deb

Note: make sure to use your own version of the .deb package. Now start the docker

Now, we successfully install docker.

Check the Docker Version:

docker --version

Uninstall Docker:

Uninstall docker, CLI, Containerd, and Docker Compose packages using the following command

sudo apt-get purge docker-ce docker-ce-cli containerd.io docker-compose-plugin

Now, delete all images, containers, and volumes

sudo rm -rf /var/lib/docker
 sudo rm -rf /var/lib/containerd

Share:

Tuesday, July 26, 2022

Setup Http client for API using OkHttp in Java

In this tutorial, we will learn how to use OkHttp for HTTP requests while consuming APIs.

OkHttp is an HTTP client which will do HTTP efficiently by loading faster and saving bandwidth. Using OkHttp is easy. Its request/response API is designed with fluent builders and immutability. It supports both synchronous blocking calls and async calls with callbacks.

Setup the OkHttp dependency:

If we are using the external Jar file, download the jar from okhttp maven.

Follow this tutorial for setting up the Jar file How to add external jar or library on IntelliJ IDEA project

Setup in maven project:

Add in pom.xml

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.10.0</version>
</dependency>

Setup in Gradle project:

Add in build.gradle under "dependencies"

dependencies {
//other dependencies
 
compile("com.squareup.okhttp3:okhttp:4.10.0")
}

Implementation:

Let's create a sample java class HttpClient.java and set up the OkHttp3 client.

import okhttp3.MediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.Response

class HttpClient {

    public static final MediaType JSON = MediaType.get("application/json; charset=utf-8")


    public static Response doGetRequest(url, String apiKey = '') {
        Request.Builder requestBuilder = new Request.Builder()
                .url(url)
        Request request = setHeadersConfig(requestBuilder, apiKey).build();
        Response response = getClient().newCall(request).execute()
        return response.body().string();
    }

    public static String doPostRequest(String json, String url, String apiKey = '') {
        RequestBody body = RequestBody.create(json, JSON)
        Request.Builder requestBuilder = new Request.Builder()
                .url(url)
                .post(body)
        Request request = setHeadersConfig(requestBuilder, apiKey).build();
        Response response = getClient().newCall(request).execute()
        return response.body().string()
    }

    public static String doDeleteRequest(String json, String url, String apiKey = '') {
        RequestBody body = RequestBody.create(json, JSON)
        Request.Builder requestBuilder = new Request.Builder()
                .url(url)
                .delete(body)
        Request request = setHeadersConfig(requestBuilder, apiKey).build();
        Response response = getClient().newCall(request).execute()
        return response.body().string()
    }

    private static Request.Builder setHeadersConfig(Request.Builder requestBuilder, String apiKey) {
        requestBuilder.header("Content-Type", "application/json")
                .header("X-MBX-APIKEY", apiKey)
        return requestBuilder
    }

    private static OkHttpClient getClient() {
        return new OkHttpClient()
    }
}

This class contains the setup for the post, get and delete request.

Method setHeadersConfig is for setting up the headers we used sample X-MBX-APIKEY header configuration to set the API key. You can use your desired header configuration there.

We can pass the post body by formatting the data in JSON string.

Please don't forget to handle the Exception.

Getting Status Code:

We can get the status code from the Response response object in the above example as below:

 Response response = getClient().newCall(request).execute()
        int statusCode = response.code()

Using it from Java classes:

All the methods are static so we can simply use it from other java classes as below:

HttpClient.doPostRequest(json, url, apiKey)
Share:

Sunday, July 24, 2022

How to watch the change in arrays and objects in VueJs

In this tutorial, we will learn how to watch the nested data like arrays and objects in Vue.js

Watching Props Arrays:

export default {
  name: "ComponentName",
  props: {
    users: {
      type: Array,
      required: true,
    },
  },
  watch: {
    users: {
      deep: true,
      handler(newValue, oldValue) {
        console.log("Manipulate new and old value here")
      }
    }
  },
}

Here we are using the users array and watching it inside the watch block. deep: true will let Vue to watch inside the array and the handler will give the old and new values.

Watching Objects:

export default {
  name: "ComponentName",
  data() {
    return {
      entity: {
        properties: [],
        propertyOne:'',
        propertyTwo:''
      }
    }
  },
  watch: {
    entity: {
      deep: true,
      handler(newValue, oldValue) {
        console.log("Manipulate new and old value here")
      }
    }
  },
}

Here, we are creating the entity object and watching it in the watch block. Here it will deep watch the whole entity object.

Watching properties of Objects:

If we don't want to watch for every change on the object, we can watch every single entity as well

export default {
  name: "ComponentName",
  data() {
    return {
      entity: {
        properties: [],
        propertyOne:'',
        propertyTwo:''
      }
    }
  },
  watch: {
    'entity.properties': {
      handler(newValue, oldValue) {
        console.log("Manipulate new and old value here")
      },
      deep: true
    },
    'entity.propertyOne': {
      handler(newValue, oldValue) {
        console.log("Manipulate new and old value here")
      },
    },
  },
}

Watching properties of Objects using computed:

export default {
  name: "ComponentName",
  data() {
    return {
      entity: {
        properties: [],
        propertyOne:'',
        propertyTwo:''
      }
    }
  },
  computed: {
    entityPropertyOne() {
      return this.entity.propertyOne;
    }
  },
  watch: {
    entityPropertyOne: {
      handler(newValue, oldValue) {
        console.log("Manipulate new and old value here")
      },
    },
  },
}
Share:

How to parse JSON string to Object and vice versa in Groovy Grails application

In this tutorial, we will learn how to parse or convert the object to JSON string and JSON string to object.

Convert Object to JSON String:

Let's look into the example, here we will parse the Map to JSON string.

Map mapToConvert = [username : "Test", phonenumber : "+10656564"]
List listToConvert = ["Test", "+10656564"]

Now, let's convert to JSON string using JSON class

import grails.converters.JSON
        Map mapToConvert = [username : "Test", phonenumber : "+10656564"]
        List listToConvert = ["Test", "+10656564"]
        String jsonStringFromMap =  (mapToConvert as JSON).toString()
        String jsonStringFromList =  (listToConvert as JSON).toString()
        

You can use any other object data type to convert as above

Convert JSON String to Object:

For converting JSON string to object we are using JsonSlurper as below:

import grails.converters.JSON
import groovy.json.JsonSlurper
		Map mapToConvert = [username : "Test", phonenumber : "+10656564"]
        List listToConvert = ["Test", "+10656564"]
        String jsonStringFromMap =  (mapToConvert as JSON).toString()
        String jsonStringFromList =  (listToConvert as JSON).toString()
        Map convertedMap = parseTo(jsonStringFromMap)
        List convertedList = parseTo(jsonStringFromList)
        
        private static def parseTo(String jsonString) {
        return new JsonSlurper().parseText(jsonString)
    }
        
Share:

Tuesday, July 19, 2022

Java round double to decimal places with up and down rounding

This is a quick tutorial on how we can round the double or float value to x decimal places

Here we are using DecimalFormat class to do so. Let's look at the example. Here we are creating DecimalFormatter.java class

Round to x decimal places:

import java.text.DecimalFormat;

public class DecimalFormatter {

    public static void main(String[] args) {
        // normal format
        System.out.println("Normal format: " + format(2.0451, "0.00"));
        System.out.println("Normal format add extra zero: " + format(2.045, "0.00000"));
    }
    
    private static String format(double value, String precision) {
        DecimalFormat df = new DecimalFormat(precision);
        return df.format(value);
    }
}    

In the above example, we are using a default rounding mode i.e DecimalFormat by default uses half even rounding mode to format. i.e if the decimal value is greater or equal to 5 then it will round up for that precision else use the same value for that precision. Here, 2.0451 will be formatted to 2.05 as we are using the two decimal place 0.00

Also, in the second example, we have a double value of 2.045 but we are trying to round 0.00000 five decimal places so it will add the extra 2 zeros to the double value.

Output:

Normal format: 2.05
Normal format add extra zero: 2.04500

Round Up to x decimal places:

import java.math.RoundingMode;
import java.text.DecimalFormat;

public class DecimalFormatter {

    public static void main(String[] args) {
        // round up format
        System.out.println("Round up format: " + formatRoundUp(1.03510001, "0.0000"));
    }
    
     private static String formatRoundUp(double value, String precision) {
        DecimalFormat df = new DecimalFormat(precision);
        df.setRoundingMode(RoundingMode.UP);
        return df.format(value);
    }
}    

Here, we are setting rounding mode to Up for DecimalFormat so it will round up the decimal value, whether it is greater or equal to 5 or not for the given decimal places.

Output:

Round up format: 1.0352

Round Down to x decimal places:

import java.math.RoundingMode;
import java.text.DecimalFormat;

public class DecimalFormatter {

    public static void main(String[] args) {
        // round down format
        System.out.println("Round down format: " + formatRoundDown(1.0316, "0.000"));
    }
    
	private static String formatRoundDown(double value, String precision) {
        DecimalFormat df = new DecimalFormat(precision);
        df.setRoundingMode(RoundingMode.DOWN);
        return df.format(value);
    }
}    

In the above example, we are setting rounding mode to Down such that it will round down the decimal value whether it is greater or equal to 5.

Output:

Round down format: 1.031
Share:

Saturday, July 9, 2022

Setup and run Appium for Android with Java client on Linux

How to set up and run Appium for android apps with Java client with Emulator setup.
1. Introduction:

Appium is an open-source automation tool for mobile applications. It is a cross-platform tool that is used to automate native, hybrid, and mobile web applications running on ios, android, and windows platforms. In this tutorial, we are going to set up Appium and run a sample example.


2. prerequisites:

  1. Installed JDK
  2. NodeJs
3. Download and run Appium:

Download the latest version of the Appium desktop App Image from here. Under "Assets" download AppImage for Linux. Go to download directory and open terminal. Give permission for the app image file.

 
chmod a+x

Now, execute the AppImage file either by double-clicking it or running the following command.
./AppImage
You can see as the Appium Ui started similar to this.


Now, start the Appium server with default port 4723 by clicking the "Start Server" button.




4. Setup Android Emulator:

In order to set up an Android Emulator, you can set it up via a command-line tool without installing an android studio but here, we are going to download an android studio and set up android SDK to run Emulator. For this download android studio from here. Extract the downloaded tar file.
 
tar -xvf android-studio.tar.gz

Go to the extracted directory cd to the bin directory you can see the studio.sh simply execute this sh file by opening the terminal. Which will popup the android studio setting import option. Select "Do not import settings". Click "Next", select "Standard" and verify the setting. Make sure to verify the path of SDK installed.


Click "Next" and "Finish" which will download the SDK on the SDK folder mentioned.

Now, we need to configure the android virtual device for this click "Configure" and select "AVD Manager".


If you see "dev/kvm device: permission denied" you can give permission for the user by using the command:
sudo chown yourLinuxUser /dev/kvm
Create a Virtual Device







After that, select the downloaded image and click "Next" and verify android virtual device configuration and click "Finish" to finish the virtual device setup. Now you can launch the virtual device in the Emulator.



Now, let's configure the SDK path in our system. For this open bashrc file by using the command:
 
  sudo gedit ~/.bashrc

Add the following line at the end of the file.
 
  export ANDROID_HOME=/home/kchapagain/Downloads/Sdk
export PATH=$ANDROID_HOME/emulator:$ANDROID_HOME/tools:$PATH
export PATH=$PATH:$ANDROID_HOME/platform-tools
Make sure you provided the correct download SDK path in "ANDROID_HOME" in my case it's "/home/kchapagain/Downloads/Sdk". Save the file and reload the changes by using the command:
 
  source ~/.bashrc

You can launch the device on Emulator via the command line so that you don't need to open the android studio each time you run the device. For this, open the terminal use command:
emulator -list-avds
Output:
Pixel_2_API_28
Pixel_2_API_28_2

Here, we have two virtual devices installed in your case it will output the list of devices downloaded.

Now, run the device on the Emulator using command:
emulator -avd Pixel_2_API_28
User your device name instead "Pixel_2_API_28". It will run the android virtual device on Emulator.

 
5. Download and load library for Java Client:

Download the Appium java client jar from here.



Similarly, download JUnit jar from here.  Download selenium from here.

Create a java project and create a package called "libs" under "src". Copy all the downloaded jar file in this package and load the jar file from Ide.

For IntelliJ Idea:

Go to: File >> Project Structure(Ctr + Alt + Shift + s) >> Libraries and click the + icon on the top left corner and select package.


6. Setup driver config for Appium:

Create a sample class to config the android driver. Here, we are using the sample calculator app to test and the driver setup config looks like below:
 @Before
    public static void setUp() throws MalformedURLException {
        DesiredCapabilities cap = new DesiredCapabilities();
        cap.setCapability("platformName", "Android");
        cap.setCapability("deviceName", "50b6ab0");
        cap.setCapability("appPackage", "");
        cap.setCapability("appActivity", "");
        cap.setCapability("automationName", "UiAutomator1");
        cap.setCapability("autoGrantPermissions", true);
        cap.setCapability("autoAcceptAlerts", "true");
        driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), cap);
    }
Share:

How to call parent window function from child window in javascript

In this tutorial, we will learn how to call the parent window function from the child window in javascript.

In some cases, we need to open the child browser window as a modal or dialog. For example, if need to handle and load the redirect URL in a single-page application.

While using third-party services providers for e.g PayPal we are supposed to get the redirect URL to load the payment page for security reasons. In this case, we will load that redirect URL in the child window as a modal and the user will proceed with the payment securely. Once the payment is done we need to notify the parent window or our single-page application that the payment got succeeded or pass some token. In this case, we need to call the parent window function from the child window.

Let's look into the example, where we are passing token from the child window to the parent function.

Here, while opening the child window we will register the function in the document interface that represents any web page loaded in the browser and serves as an entry point into the web page's content

document.responseToken = function (token){
          // manuplate the token
        }

Now let's add the calling function from the child window.

window.opener.document.responseToken(token);
        window.close();

Here, we are using window.opener The Window interface's opener property returns a reference to the window that opened the window i.e parent window. So we can get the responseToken function that we registered previously. This will pass the token to the reference or parent window. After that window.close() will close the child dialog window.

Share:

Tomcat Invalid character found in the request target

While running an application in the tomcat server, sometimes we might get the following error.

org.apache.coyote.http11.Http11Processor.service Error parsing HTTP request header
 Note: further occurrences of HTTP request parsing errors will be logged at DEBUG level.
	java.lang.IllegalArgumentException: Invalid character found in the request target [/index.php?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=md5&vars[1][]=HelloThinkPHP21 ]. The valid characters are defined in RFC 7230 and RFC 3986
		at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:509)
		at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:511)
		at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
		at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:831)
		at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1673)
		at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
		at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
		at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
		at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
		at java.lang.Thread.run(Thread.java:748)

First, make sure that the domain pointed to the server is working fine or not expired.

From tomcat, it is suggested that

The HTTP/1.1 specification requires that certain characters are %nn encoded when used in URI query strings. Unfortunately, many user agents including all the major browsers are not compliant with this specification and use these characters in unencoded form. To prevent Tomcat rejecting such requests, this attribute may be used to specify the additional characters to allow. If not specified, no additional characters will be allowed. The value may be any combination of the following characters: " < > [ \ ] ^ ` { | } . Any other characters present in the value will be ignored.

Tomcat increased its security and no longer allows raw square brackets or the above characters in the query string.

In order to resolve this issue use relaxedQueryChars attributes inside the server.xml file of tomcat server. Make sure to back up the server.xml file before we change it.

Open the server.xml file using vim or vi and type Shift + i

sudo vim /path_to_tomcat/conf/server.xml

Press Esc and hit :wq! and save the changes

Restart the tomcat server.

Share:

Thursday, July 7, 2022

How to use custom validation class in Grails Application

In this tutorial, we will learn how to add custom validation in the Grails application.

Grails domain classes support the validation by default. So we can simply add the constrains for the domain classes fields as below

class User {
    String username
    String password
    String email
    Integer age
    
    
	static constraints = {
        username blank: false, unique: true
        password size: 5..15, blank: false
        email email: true, blank: false
        age min: 18
	}
}

Now we can simply validate the object using validate() or hasErrors() methods

User user = new User(params) // map the request parameters to user object
if (!user.validate()) {
    // format errors and send to the client
}
User user = new User(params) // map the request parameters to user object
if (user.hasErrors()) {
    // format errors and send to the client
}

Now, let's say that we want to validate some non-domain fields or use a custom validation class to validate the request parameter sent by the user.

We can do so by implementing Validateable trait so that we can add the constrain for the fields in the custom class. Let's look into the example

import grails.validation.Validateable

class UserCommand implements Validateable {

    public static final emailRegex = "^\\w+([\\.-]?\\w+)*@\\w+([\\.-]?\\w+)*(\\.\\w{2,3})+\$"

    UserCommand(def requestParams) {
        email = requestParams.email
        password = requestParams.password
        username = requestParams.username
        age = requestParams.age
    }

    static constraints = {
        username blank: false, unique: true
        password size: 5..15, blank: false
        email email: true, blank: false, validator: emailValidator
        age min: 18
    }
    
    static emailValidator = { String value, UserCommand command ->
        if (!value.find(emailRegex)) {
            return "email.invalid" // getting message from message.properties file
        }
    }
}

In the above example, we can add the constraints after implementing the Validateable on the custom class and do the validation logic similar to the domain classes validation.

Now, let's utilize the above command class inside the controller.

UserCommand userCommand = new UserCommand(requestParams)
        if (!userCommand.validate()) {
            Map result = [success: false, errors: []]
            result.errors = getCommandErrors(userCommand)
            render(result as JSON)
            return
        }
def messageSource

public static List getCommandErrors(def command) {
        List errors = []
        command.errors.allErrors.each { ObjectError error ->
            String msg = messageSource.getMessage(error.code, error.arguments, error.defaultMessage)
            errors.add(msg)
        }
        return errors
    }

For more details visit Grails Validation

Share:

Wednesday, July 6, 2022

How to enable CORS in Grails Application

In this tutorial, we are going to learn how to enable the cross-origin resources sharing CORS in a Grail Application.

Introduction:

Cross-origin resource sharing is the way to trust between the two web services or applications. So if the two web services don't satisfy then a CORS issue may arise.

Cors is a mechanism for the web application that controls listening to certain request from other web applications which is not hosted on the same server. It will not grant access to the content from other applications. So, in order to interact between two different web applications, we need to enable the Cors for that particular app.

Enable CORS in Grails Application:

We can enable cors in application.yml as below

grails:
    cors:
        enabled: true

The above configuration enables the cors for all the origins i.e all applications can interact with our application.

Enable Cors for a specific domain:

application.yml

grails:
    cors:
        enabled: true
        allowedOrigins:
            - https://example.com

This will allow the request only for the domain example.com

Enable Cors for specific requests or URLs:

application.yml

grails:
    cors:
        enabled: true
        allowedHeaders:
            - Content-Type
        mappings:
            '[/api/**]':
                allowedOrigins:
                    - https://example.com

This will allow all the requests from URLs that start with /api for example.com domain. Note that the mapping key must be made with bracket notation i.e [/api/**]

For more detail please visit Grails CORS.

Share:

How to create Local and Remote Tags on Git

This is a quick tutorial on how to create a Tag in Git

Creating the Tag in Git is important because it gives the ability to mark or point to a repository's history.

Basically, we will release the tag once the new version is deployed and finalized. By doing so, if we need the previous Tag version code, we can create a new branch from this tag and use the branch for further manipulation.

Create a Tag:

Before creating the tag make sure to switch to the branch where we want to create a Tag. Use the following command to switch the branch.

git checkout development

Here, development is the branch name to switch, use your own branch name.

Create a tag:
git tag -a v0.0.1-06-07-2022 -m "version 0.0.1 released"

This will create the tag with the name v0.0.1-06-07-2022; please use your own version name and "version 0.0.1 released" as a message

List the Tag:

Now, let's list the available tags created.

git tag

We can see all the created tag output below.

v0.0.1-06-07-2022

Push to the repository:

Once the tag is created it will available only locally. If we are using a code management service provider like Github, Bitbucket, or Gitlab then we need to push the tag to a point on the repository. Use the following command to push

git push origin v0.0.1-06-07-2022

Once the tag is pushed we can see the output similar to below

Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 176 bytes | 176.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To https://bitbucket.org/repo_name.git
 * [new tag]         v0.0.1-06-07-2022 -> v0.0.1-06-07-2022

Delete the Tag:

Let's first delete the tag created from the remote.

git push --delete origin v0.0.1-06-07-2022

Once the tag is deleted we can see the output similar as below

To https://bitbucket.org/repo_name.git
 - [deleted]         v0.0.1-06-07-2022

Now, let's delete the tag from locally

git tag -d v0.0.1-06-07-2022
Share:

Binance API code -1013 msg - Filter failure: PRICE_FILTER

While implementing the Binance API, we might get the following error.

{
"code":-1013,
"msg":"Filter failure: PRICE_FILTER"
}

This might be due to the mismatch of the given Filter for the price by Binance. As from the Binance Spot Api documentation, the condition that needs to be satisfied is

price >= minPrice
price <= maxPrice
price % tickSize == 0

We can get the Filter value for PRICE_FILTER as below.

For BTC USDT:

https://api.binance.us/api/v3/exchangeInfo?symbol=BTCUSDT

OR

https://api.binance.com/api/v3/exchangeInfo?symbol=BTCUSDT

The output of the above endpoint is:

{
   "timezone":"UTC",
   "serverTime":1657086978303,
   "rateLimits":[
      {
         "rateLimitType":"REQUEST_WEIGHT",
         "interval":"MINUTE",
         "intervalNum":1,
         "limit":1200
      },
      {
         "rateLimitType":"ORDERS",
         "interval":"SECOND",
         "intervalNum":10,
         "limit":100
      },
      {
         "rateLimitType":"ORDERS",
         "interval":"DAY",
         "intervalNum":1,
         "limit":200000
      },
      {
         "rateLimitType":"RAW_REQUESTS",
         "interval":"MINUTE",
         "intervalNum":5,
         "limit":6100
      }
   ],
   "exchangeFilters":[
      
   ],
   "symbols":[
      {
         "symbol":"BTCUSDT",
         "status":"TRADING",
         "baseAsset":"BTC",
         "baseAssetPrecision":8,
         "quoteAsset":"USDT",
         "quotePrecision":8,
         "quoteAssetPrecision":8,
         "baseCommissionPrecision":8,
         "quoteCommissionPrecision":8,
         "orderTypes":[
            "LIMIT",
            "LIMIT_MAKER",
            "MARKET",
            "STOP_LOSS_LIMIT",
            "TAKE_PROFIT_LIMIT"
         ],
         "icebergAllowed":true,
         "ocoAllowed":true,
         "quoteOrderQtyMarketAllowed":true,
         "allowTrailingStop":false,
         "cancelReplaceAllowed":false,
         "isSpotTradingAllowed":true,
         "isMarginTradingAllowed":false,
         "filters":[
            {
               "filterType":"PRICE_FILTER",
               "minPrice":"0.01000000",
               "maxPrice":"100000.00000000",
               "tickSize":"0.01000000"
            },
            {
               "filterType":"PERCENT_PRICE",
               "multiplierUp":"5",
               "multiplierDown":"0.2",
               "avgPriceMins":5
            },
            {
               "filterType":"LOT_SIZE",
               "minQty":"0.00000100",
               "maxQty":"9000.00000000",
               "stepSize":"0.00000100"
            },
            {
               "filterType":"MIN_NOTIONAL",
               "minNotional":"10.00000000",
               "applyToMarket":true,
               "avgPriceMins":5
            },
            {
               "filterType":"ICEBERG_PARTS",
               "limit":10
            },
            {
               "filterType":"MARKET_LOT_SIZE",
               "minQty":"0.00000000",
               "maxQty":"29.33387056",
               "stepSize":"0.00000000"
            },
            {
               "filterType":"MAX_NUM_ORDERS",
               "maxNumOrders":200
            },
            {
               "filterType":"MAX_NUM_ALGO_ORDERS",
               "maxNumAlgoOrders":5
            }
         ],
         "permissions":[
            "SPOT"
         ]
      }
   ]
}

For PRICE_FILTER:

{
               "filterType":"PRICE_FILTER",
               "minPrice":"0.01000000",
               "maxPrice":"100000.00000000",
               "tickSize":"0.01000000"
            },

Lets look into the first condition; price >= minPrice price <= maxPrice

We need to have a price that must be greater or equal to min price and less than or equal to the max price.

Let's look into the second condition: price % tickSize == 0; For this, we might get the precision issue if we don't parse the price. Here, tickSize is in the 2 decimal place so we need to parse the price in 2 decimal places to validate the filter. This will help resolve the issue.

Share:

Tuesday, July 5, 2022

Binance Api code-1013 msg:Filter failure: MIN_NOTIONAL

This is a quick tutorial on how we can resolve the Filter failure: MIN_NOTIONAL

While using Binance API, when placing the order and calling API we might get the following error.

{
"code":-1013,
"msg":"Filter failure: MIN_NOTIONAL"
}

As described on binance spot API documentation, The MIN_NOTIONAL filter defines the minimum notional value allowed for an order on a symbol. An order's notional value is the price * quantity

Now let's look into what is the required values for MIN_NOTIONAL. We can get it from the exchange info endpoint as below

For BTC USDT

https://api.binance.us/api/v3/exchangeInfo?symbol=BTCUSDT

The Output for the above endpoint is:

{
   "timezone":"UTC",
   "serverTime":1657007585516,
   "rateLimits":[
      {
         "rateLimitType":"REQUEST_WEIGHT",
         "interval":"MINUTE",
         "intervalNum":1,
         "limit":1200
      },
      {
         "rateLimitType":"ORDERS",
         "interval":"SECOND",
         "intervalNum":10,
         "limit":100
      },
      {
         "rateLimitType":"ORDERS",
         "interval":"DAY",
         "intervalNum":1,
         "limit":200000
      },
      {
         "rateLimitType":"RAW_REQUESTS",
         "interval":"MINUTE",
         "intervalNum":5,
         "limit":6100
      }
   ],
   "exchangeFilters":[
      
   ],
   "symbols":[
      {
         "symbol":"BTCUSDT",
         "status":"TRADING",
         "baseAsset":"BTC",
         "baseAssetPrecision":8,
         "quoteAsset":"USDT",
         "quotePrecision":8,
         "quoteAssetPrecision":8,
         "baseCommissionPrecision":8,
         "quoteCommissionPrecision":8,
         "orderTypes":[
            "LIMIT",
            "LIMIT_MAKER",
            "MARKET",
            "STOP_LOSS_LIMIT",
            "TAKE_PROFIT_LIMIT"
         ],
         "icebergAllowed":true,
         "ocoAllowed":true,
         "quoteOrderQtyMarketAllowed":true,
         "allowTrailingStop":false,
         "cancelReplaceAllowed":false,
         "isSpotTradingAllowed":true,
         "isMarginTradingAllowed":false,
         "filters":[
            {
               "filterType":"PRICE_FILTER",
               "minPrice":"0.01000000",
               "maxPrice":"100000.00000000",
               "tickSize":"0.01000000"
            },
            {
               "filterType":"PERCENT_PRICE",
               "multiplierUp":"5",
               "multiplierDown":"0.2",
               "avgPriceMins":5
            },
            {
               "filterType":"LOT_SIZE",
               "minQty":"0.00000100",
               "maxQty":"9000.00000000",
               "stepSize":"0.00000100"
            },
            {
               "filterType":"MIN_NOTIONAL",
               "minNotional":"10.00000000",
               "applyToMarket":true,
               "avgPriceMins":5
            },
            {
               "filterType":"ICEBERG_PARTS",
               "limit":10
            },
            {
               "filterType":"MARKET_LOT_SIZE",
               "minQty":"0.00000000",
               "maxQty":"29.33387056",
               "stepSize":"0.00000000"
            },
            {
               "filterType":"MAX_NUM_ORDERS",
               "maxNumOrders":200
            },
            {
               "filterType":"MAX_NUM_ALGO_ORDERS",
               "maxNumAlgoOrders":5
            }
         ],
         "permissions":[
            "SPOT"
         ]
      }
   ]
}

For MIN_NOTIONAL:

{
               "filterType":"MIN_NOTIONAL",
               "minNotional":"10.00000000",
               "applyToMarket":true,
               "avgPriceMins":5
            },

So this defines that the limit order placed must be minimum of $10 i.e price * quantity = total here, the total must be at least 10. If this doesn't satisfy then we will get the mentioned error. So the condition must be satisfied while calling the API.

Share:

Saturday, July 2, 2022

Vue.js How to get query parameter from URL

In this tutorial, we are going to learn how we can get the query parameter from URL.

let's look into the sample example.

http://360learntocode.com?username=test

Using Vue Router:

Here, we want to get the username query parameter. In Vue.js there is an elegant way to get query parameters. If we are using the router then we can get the parameter inside the vue.js component as below.

let username =  this.$route.query.username

Which gives the username value. Another way to get parameters with the router is

let username = this.$route.params.username

Using Javascript URLSearchParams :

We can use URLSearchParams() method which helps to work with the query string of the URL. We can use this inside our vue.js component methods as below.

 methods: {
    getUsername() {
      const queryString = window.location.search;
      if (queryString) {
        const urlParams = new URLSearchParams(queryString);
      	if (urlParams.has('username')) {
          return urlParams.get('username');
        }
      }
      return "";
    }
  }

Or

 methods: {
    getUsername() {
      const queryString = window.location.href;
      if (queryString) {
      	let urlString = queryString.split('?')[1]
        const urlParams = new URLSearchParams(urlString);
      	if (urlParams.has('username')) {
          return urlParams.get('username');
        }
      }
      return "";
    }
  }
Share:

Error: Could not find or load main class org.grails.cli.GrailsCli

This is a quick tutorial on how we can resolve the issue on the Grails project.

For grails application sometimes we might get the following error

Error: Could not find or load main class org.grails.cli.GrailsCli

This might be due to the removal of some dependencies or libraries from the application. Sometimes, while loading multiple applications from IDE while downloading the library for a particular project other libraries for another project might remove so this kind of error might occurs for that project.

Let's first delete the build folder under the application.

Now, let's refresh the Gradle project. Here we are using IntelliJ Idea, we can refresh the project as below

After refreshing the project it will download the missing dependencies. Then run the application which will resolve the problem.

We can also try cleaning the application.

If we are using the command line then type the following command to clean the application.

grails clean

If we are using the IntelliJ idea then Ctr+Alt+G opens the command window and use the following command.

clean

Now, re-run the app. This will help resolve the issue.

Share:

Friday, July 1, 2022

Error while importing mysql dump sql file Unknown collation: utf8mb4_0900_ai_ci

This is a quick tutorial on how we can resolve the issue while importing the MySQL dump SQL file. Sometimes due to the incompatibility of the MySQL version, the following error might occurs

ERROR 1273 (HY000): Unknown collation: 'utf8mb4_0900_ai_ci'

Before resolving the issue, make sure to back up the dump SQL file

sudo cp sql_file_name.sql sql_file_name_backup.sql 

In order to resolve this issue, we are going to replace the collation utf8mb4_0900_ai_ci with the valid collation utf8_general_ci. For this open, the SQL file with vim or vi and hit Shift + : and add the following replace command and hit enter.

%s/utf8mb4_0900_ai_ci/utf8_general_ci/g

The above command will find each occurrence of 'utf8mb4_0900_ai_ci' (in all lines), and replace it with 'utf8_general_ci'.

Now lets change the CHARSET=utf8mb4 to CHARSET=utf8

%s/utf8mb4/utf8/g

Make sure to hit enter after each command.

Now save the file by Shift+: and type wq!

After the changes, import the dump SQL file which supposes to work fine.

Share:

How to add external jar or library on IntelliJ IDEA project

In this tutorial, we will learn how to add external jar files to the project and load it using Intellij Idea.

Load Jar for Simple Java Application:

Let's create a directory called libs under the project root directory and add all the external libraries. Now we need to load those Jar files using Intellij Idea.

In Intellij, click on >> File >> Project Structure or hit Ctrl + Alt + Shift + s. This will open the popup window to load library.

Note: Select the New project library as Java in step 2 as shown in the figure.

Then click ok to load the libs folder module and click on Apply and Ok. Now we can access the Jar from our java classes.

Loading Jar/Library from Gradle Project:

Add the following inside dependencies in build.gradle file.

dependencies {
//other dependencies
 
compile fileTree(dir: 'libs', include: '*.jar')
}

After that in IntelliJ idea you can see the Gradle on the right side, click on it and refresh the Gradle project as below:

Loading Jar/Library from Maven Project:

Add the following system dependency inside pom.xml file.

<dependency>
           <groupId>com.libName</groupId>
           <artifactId>lib-artifact</artifactId>
           <version>20220117</version>
           <scope>system</scope>
           <systemPath>${basedir}/libs/jar_file_name.jar</systemPath>
       </dependency>

Make sure to change the group id, artifact id, and system path.

After that from the IntelliJ idea on the right side, you can see the Maven click on it and refresh the project by clicking the project name as below.

Share:

How to deploy the war file on remote tomcat server

In this tutorial, we are going to learn basic steps to deploy our war file to the tomcat server.

Create a war file:

First, create a war file, this will depend upon the framework used, each framework will provide the command to create a war file. The war file will contain the extension with .war.

Connect to remote server:

Now, let's connect to a remote server where we want to deploy to war file. Here we are SSH connection to the server

If you are using a server password to connect using the following command

sudo ssh server_username@ip_address

Here use your server username and server IP address to connect. For example ubuntu@34.344.56

If you are using a .pem file or other private keys to connect to a server then use the following command

sudo ssh -i path_to_pem_file server_username@ip_address

Download tomcat on the remote server:

Once ssh to a remote server, let's download the tomact server where we will deploy our war file.

Here, we are using tomcat 8 so will download the same.

sudo wget https://dlcdn.apache.org/tomcat/tomcat-8/v8.5.81/bin/apache-tomcat-8.5.81.tar.gz

Extract the file

sudo tar xvzf apache-tomcat-8.5.81.tar.gz

Here, generally, we put the extracted tomcat server under /opt directory of the system.

In this tutorial, we are not using tomcat GUI to make it simple for set up. so let's remove the unnecessary folder from the tomcat server.

sudo rm -r apache-tomcat-8.5.81/webapps/*

Copy war file to remote server:

Now, let's copy the war file to deploy.

sudo scp path_to_war/war_file_name.war server_username@ip_address:~

This will copy the war file into the home directory of the remote server. If you are using .pem file or other private keys then use the following command to copy the war file.

sudo scp -i path_to_pem_file path_to_war/war_file_name.war server_username@ip_address:~

Once the war file is copied and moved to the remote server then, ssh to the remote server if not ssh.

Deploy War file:

First, give sufficient permission for copied war file

sudo chmod 555 war_file_name.war

Copy war file to the webapps directory of our tomcat server

sudo mv war_file_name.war /opt/apache-tomcat-8.5.81/webapps/ROOT.war

Note: make sure that you should copy the war file as ROOT.war inside webapps directory

Install Java:

Tomcat server requires java to run. So let's install java; here, we are using OpenJDK 8 using the following command.

sudo apt-get install openjdk-8-jdk

Confirm the installation

java -version

We can see the similar output

openjdk version "1.8.0_312"
OpenJDK Runtime Environment (build 1.8.0_312-8u312-b07-0ubuntu1~20.04-b07)
OpenJDK 64-Bit Server VM (build 25.312-b07, mixed mode)

Run the Tomcat server:

First, navigate to the tomcat directory and use the below command to run the tomcat server

cd /opt/apache-tomcat-8.5.81/
sudo sh bin/startup.sh

If the tomcat server is running successfully then you are supposed to see the output similar as below

Using CATALINA_BASE:   /opt/apache-tomcat-8.5.81
Using CATALINA_HOME:   /opt/apache-tomcat-8.5.81
Using CATALINA_TMPDIR: /opt/apache-tomcat-8.5.81/temp
Using JRE_HOME:        /usr
Using CLASSPATH:       /opt/apache-tomcat-8.5.81/bin/bootstrap.jar:/opt/apache-tomcat-8.5.81/bin/tomcat-juli.jar
Using CATALINA_OPTS:   
Tomcat started.

See the logs of tomcat:

Once Tomcat is running successfully, we need to verify whether the war file is running as expected or not

sudo tail -f logs/catalina.out

This will give the last log file lines; if you want to specify how many lines to view then replace f with e.g 1000 to see the 1000 lines log.

Stop the Tomcat server:

sudo sh bin/shutdown.sh

If the app is running fine, you can open the application using the public IP address or with the domain name if pointed to that IP address.

http://example.com:8080

Or

http://124.56.234:8080

Here, the tomcat server will run with port 8080 by default.

Change the port 8080 to 80:

Under server.xml you can find the following tag.

change the above XML tag as below:

Here, we are changing the port from 8080 to 80 and 8443 to 443. By doing so, if your domain running with port 8080 i.e example.com:8080, now it will open with port 80 i.e example.com. If you type your domain in the browser then you can run it with both HTTP and HTTPS i.e http://example.com and https://example.com.

Save the server.xml file and re-run the tomcat server by first stopping it.

Share: