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:

Thursday, June 30, 2022

Create Mysql User and Grant Privileges

In this tutorial, we are going to learn how we can create MySQL users and grant privileges to that users.

For MySQL installation please follow the tutorial, Install Mysql Specific Version on Ubuntu.

Create MySQL User:

Before creating a new user we need to first log in with the root user, for this, use the following command.

mysql -u username -puserpassword

Here, username is the root user's username and userpassword is the root user's password, use your root user's username and password.

Now, let's create the user

CREATE USER 'username'@'localhost' IDENTIFIED BY 'password';

Replace the username with your desired new user name and password as desired strong password. Here we are using localhost as we are considering the MySQL setup from the same server, if it is for the remote server then use IP address of host/server as below.

CREATE USER 'username'@'ip_address' IDENTIFIED BY 'password';

For this created user, they can access the database from that server not remotely. If we want to create user that can connect from any server or machine as below.

CREATE USER 'username'@'%' IDENTIFIED BY 'password';

Grant Privileges:

The general syntax for grant privileges is

GRANT <privileges_type> ON <database_table> TO 'username'@'localhost';

Let's look into some examples

Grant all privileges to user for all database

GRANT ALL PRIVILEGES ON *.* TO 'username'@'localhost';

Here, *.* will grant for all databases, and "ALL PRIVILEGES" will grant all the privileges

Grant all privileges to the user for a particular database

GRANT ALL PRIVILEGES ON database_name.* TO 'username'@'localhost';

database_name.* will grant all privileges for all the tables of that database with the database name "database_name"

Grant all privileges to user for a particular database table

GRANT ALL PRIVILEGES ON database_name.table_name TO 'username'@'localhost';

We can do database query-specific privileges like Insert, Delete, Create, Drop, Select, Update, etc. For example

GRANT INSERT ON *.* TO 'username'@'localhost';

Here, the user can insert rows into tables for all the databases but can't do other operations like drop, create, update, etc.

Flush Privileges:

After we change the user privileges we need to flush it to reflect the changes. We can do so using following command

FLUSH PRIVILEGES;

Revoke Privileges:

We can revoke the grant privileges for the user as below

REVOKE <privileges_type> ON <database_table> FROM 'username'@'localhost';

Remove User:

We can remove the MySQL user as well by using the following command

DROP USER 'username'@'localhost';
Share:

Install Mysql Specific Version on Ubuntu/Linux using debian package

In this tutorial, we are going to install MySQL version 5.7 using the Debian package(.deb)

Step 1. Add the MySQL Apt Repository

First download the Debian(.deb) package from MySQL Apt Repo. Here we are using the wget to download as below:

wget https://dev.mysql.com/get/mysql-apt-config_0.8.12-1_all.deb

Step 2. Configure the .deb file

sudo dpkg -i mysql-apt-config_0.8.12-1_all.deb

You can see the below prompt screen

If somehow we are unable to see the prompt screen then either dpkg is interrupted or broken. Use the below command to clean the config after that use the previous dpkg command, now we can see the screen

apt-get purge mysql-apt-config

Select the ubuntu bionic option and the second screen will pop up as below. Now select the first option to select the MySQL version

Now select the desired version of MySQL, Here we are selecting the MySQL 5.7

Once selected the desired version of MySQL then select ok to configure.

Now the configure suppose to get successful and we can see the output as below:

Selecting previously unselected package mysql-apt-config.
(Reading database ... 36242 files and directories currently installed.)
Preparing to unpack mysql-apt-config_0.8.12-1_all.deb ...
Unpacking mysql-apt-config (0.8.12-1) ...
Setting up mysql-apt-config (0.8.12-1) ...
Warning: apt-key should not be used in scripts (called from postinst maintainerscript of the package mysql-apt-config)
OK

Step 3. Install the MySQL Server

Now update the MySQL repository

sudo apt-get update

Install the MySQL using the following command:

sudo apt install -f mysql-client=5.7* mysql-community-server=5.7* mysql-server=5.7*

If you chose the latest version of MySQL then no need to specify the package.

Next, the screen will pop up to enter the root password. Enter the password and press ok. After that MySQL is installed and running successfully. Test the MySQL version and MySQL status by using the below command:

mysql --version
sudo systemctl status mysql

Step 4. Secure MySQL Installation

Use the following command to secure MySQL installation:

sudo mysql_secure_installation

Enter your MySQL root password and answer all of the security questions.

Now, log in using the root credential

mysql -u root -p

Step 5. Create a New Mysql User

Before creating new users we need to first log in with the root user as mentioned above. Now, create the user using the following command:

CREATE USER 'username'@'localhost' IDENTIFIED BY 'password';

Here, use your own username and password and localhost as we are working on the same machine.

For example:

CREATE USER 'testuser'@'localhost' IDENTIFIED BY 'testpassword';

If we want to create a user that can be connected from any machine then use the following command

CREATE USER 'username'@'%' IDENTIFIED BY 'password';

Now, let's grant the permission to the newly created user.

GRANT ALL PRIVILEGES ON *.* TO 'testuser'@'localhost';

Here, user have full access to the database with ALL PRIVILEGES and for all the databases as we are using *.*

However, we can grant privileges for specific databases as

GRANT ALL PRIVILEGES ON database_name.* TO 'testuser'@'localhost';

After grant privileges to user, we need to flush the privileges

FLUSH PRIVILEGES;

We can revoke privileges using the following command:

GRANT ALL PRIVILEGES ON *.* TO 'testuser'@'localhost';

Remove User:

DROP USER 'testuser'@'localhost';

Step 6: Some commands for MySQL server:

Stop the MySQL server:

sudo systemctl stop mysql

Start the MySQL server:

sudo systemctl start mysql

Check the status of MySQL server:

sudo systemctl status mysql

Restart MySQL server

sudo systemctl restart mysql

Step 7: Completly remove/uninstall MySQL server

sudo apt-get remove --purge mysql*
sudo apt-get autoremove
sudo apt-get autoclean
Share:

Wednesday, June 29, 2022

How to use SiftingAppender in Gradle Groovy project

 In this tutorial, we are going to set up the SiftingAppender in our Gradle Groovy project.

Sifting Appender is useful when we want to separate the log files during runtime i.e if we want to separate the log files per thread or per user session basis.

Unfortunately, in the Gradle Groovy project, SiftingAppender is no longer supported since version 1.0.12 as mentioned in Groovy Configuration.

Let's look into the simple example where we are going to configure the SiftingAppender in logback.groovy, where we want to configure the per-user logging mechanism.

import ch.qos.logback.classic.PatternLayout
import ch.qos.logback.classic.sift.MDCBasedDiscriminator
import ch.qos.logback.classic.sift.SiftingAppender

appender("USER_ROLLING", SiftingAppender) {
    discriminator(MDCBasedDiscriminator) {
        key = 'userid'
        defaultValue = 'NONE'
    }
    sift {
        appender("FILE-${userid}", FileAppender) {
            file = "Path-to-log/${userid}.log"
            append = true
            layout(PatternLayout) {
                pattern = "%level %logger - %msg%n"
            }
        }
    }
}
logger("package-to-log",TRACE,['USER_ROLLING'], false)

This is a simple example SiftingAppender configuration; this is derived from logback sifting appender xml configuration.

We are using the Mapped Diagnostic Context for mapping the context user to create a separate file. We can do a similar for the thread as well.

Let's set up the MDC for user, the sample example looks as below.

import groovy.util.logging.Slf4j
import org.slf4j.MDC
@Slf4j
class UserLogging {

    public static void debug(String message, String userid = '') {
        setUserMDC(userid)
        log.debug(message)
    }

    public static void error(String message, String userid = '') {
        setUserMDC(userid)
        log.error(message)
    }

    public static void info(String message, String userid = '') {
        setUserMDC(userid)
        log.info(message)
    }

    public static void setUserMDC(String userid) {
        try {
            if (!userid) {
                MDC.remove("userid")
                return
            }
            MDC.put("userid", userid)
        }catch(e) {
            log.error("Error setting user Mapped Diagnostic Context due to "+e.getMessage())
        }
    }
}

Here, if the userid is available then we are setting the MDC for userid so the log file can be written in a separate file per user. If you want to do with request user do the similar in filter class or the place where it suits.

Now, if we run the application we will get the error as a result the appender doesn't work. So, here we found the solution project that extends Logback Gaffer so that SiftingAppender can be configured in Groovy DSL from this Github repo.

Simply download the jar file for that project and add it to the application.

For the Gradle project create a libs directory under the project directory and load and compile from build.gradle file.

Under build.gradle under dependencies{} section:

compile fileTree(dir: 'libs', include: '*.jar')

If we run the application it suppose to work. The log file will be created on the respective file path.

Share:

Tuesday, January 25, 2022

Install OpenCv in Linux/Ubuntu for Java Application.


1. Introduction:

In this blog post, we are going to install and set up OpenCV in ubuntu os for the java applications. OpenCV is a widely used great computer vision library. You can learn more about the OpenCV tutorial from here. For documentation, you can follow here. We will also cover some tutorials for Java bindings too.
 



2. Download OpenCV:

You can download OpenCV from the public Github repository of OpenCV or from their official website from here.  Select the desired version and click "Sources", which will download the zip file. Unzip the file.
unzip opencv-4.3.0.zip

 
3. Build OpenCV:

In order to build OpenCV, go to the OpenCV path in my case it's under "/opt/opencv-4.3.0" so I will use the same.

Create a directory to build.
mkdir build
  cd build
Now, if you don't have installed cmake software please install it using the below command
sudo apt-get  install cmake
Next, is to generate and configure with cmake for building executables in our system.
cmake -DBUILD_SHARED_LIBS=OFF ..
Note: When OpenCV is built as a set of static libraries (-DBUILD_SHARED_LIBS=OFF option) the Java bindings dynamic library is all-sufficient, i.e. doesn’t depend on other OpenCV libs, but includes all the OpenCV code inside. 

Make sure the output of the above command looks like below:


If it doesn't find the ant and java then you may get the following output: 
Java:
   ant:                         NO
   JNI:                         NO
   Java tests:                 YES
For this, install and setup your java and install ant
sudo apt install openjdk-8-jdk
sudo apt-get install ant

If you are still getting ant as NO then try the following command to install ant
sudo snap install ant --classic
Now start the build
make -j4
Note: Be careful not to run out of memory during the build. We need 4GB of memory per core. For example, if we compile with 4 cores (e.g. make -j4) we need a machine with at least 16GB of RAM.

The output look likes this and it will take some time.


If everything is fine, you successfully build OpenCV. Make sure the following files are packaged in the corresponding directory.
/opt/opencv-4.3.0/build/lib/libopencv_java430.so
/opt/opencv-4.3.0/build/bin/opencv-430.jar
The path of those files is created according to your OpenCV version and directory. You need to make sure the so and jar file must be created. This jar file contains the java wrapper code which we will used in the sample example.

 



4. Run Sample Example:

Now we are going to add the compiled jar file in our project library.

For IntelliJ Idea:

Go to : File >> Project Structure >> Libraries (under project settings)

you can see the + icon at the top left, to add a new project library click on it, and select java and add the path of previously created jar file i.e opencv-430.jar. 

It's time to run a sample test example.
import org.opencv.core.CvType;
import org.opencv.core.Mat;

public class SampleTest {

    public static void main(String[] args) {
        System.load("/opt/opencv-4.3.0/build/lib/libopencv_java430.so");
        Mat mat = Mat.eye(3, 3, CvType.CV_8UC1);
        System.out.println("mat = " + mat.dump());
    }
}
Make sure that you loaded your corresponding .so file.

Output:
mat = [  1,   0,   0;
   0,   1,   0;
   0,   0,   1]
For those who are running OpenCV in an existing project, you can set up with Gradle project as below:

For Gradle:

Copy the jar file in your project directory package for e.g "libs" and add following inside dependencies in build.gradle file.
dependencies {
//other dependencies

compile fileTree(dir: 'libs', include: '*.jar')
}
Share:

How to Install and configure free SSL/TLS certificate for Tomcat using Let's Encrypt on Ubuntu.

How to set up a free SSL certificate for tomcat using let's encrypt on ubuntu.

1. Introduction:



Here, we are going to set up a free SSL certificate provided by a non-profit authority called Let's Encrypt. This is trusted and used by many to secure their website. The certificate is valid for only 90 days and can renew during that time. You can find out more about Let's Encrypt here

2. Prerequisites:

  • Running ubuntu server
  • Running tomcat server
  • Domain name pointed to the server Ip address

3. Install certbort and create an SSL certificate:
SSH into the server where you want to create a certificate. In order to create an SSL certificate, we need to install certbot for this, go and select the appropriate ubuntu server version from here. As we are using ubuntu 18.04 LTS.


which will give the following command to install certbot.

Add Certbot PPA
 
 sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository universe
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
Install Certbot
sudo apt-get install certbot
If you have already running service which uses port 80, stop it first otherwise you will get Address BindException.

To obtain an SSL certificate for your domain using a built-in "standalone" webserver type the following command:
sudo certbot certonly --standalone -d example.com
Here, replace the domain name you want to secure instead of example.com 

which will create a different certificate file to the directory:   /etc/letsencrypt/live/example.com/

Now, logged in as root user and go to that directory
sudo -i
cd /etc/letsencrypt/live/example.com/

Next step is to convert those certificate PEM file to password-based PFX format so that we can use in tomcat configuration. We can do this by using OpenSSL command as below.
openssl pkcs12 -export -out bundle.pfx -inkey privkey.pem -in cert.pem -certfile chain.pem -password pass:password
Replace the password with your desired one. It will create a password-protected file bundle.pfx under the same directory "/etc/letsencrypt/live/example.com/" which we need to use in tomcat configuration.





 
4. Tomcat configuration for HTTPs:

Go to your tomcat directory, and backup the server.xml file; as we are going to change the file. It's always a good approach to backup the config file before changing it.
cp conf/server.xml conf/server-copy.xml
 
Edit the server.xml file.
sudo vi conf/server.xml  // no need to type sudo if you are logged in as root user
  
You can see the following xml tag(for tomcat 8), we are going to change this: 



Replace the above tag such that the config look like as below: 


Here, we are changing port 8443 to 443, keystoreType as "PKCS12", keystoreFile as the path of the pfx file created previously and keystorePass as your password that we used while creating PFX file. 

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 by clicking "Esc" key and type ":wq!" and hit Enter. 

As we want to always redirect our domain to https. To do so, open the web.xml file under conf/web.xml.
sudo vi conf/web.xml
  
And add the below code at the end of file before the end of "/web-app" xml tag.
<security-constraint>
  <web-resource-collection>
  <web-resource-name>Entire Application</web-resource-name>
   <url-pattern>/*</url-pattern>
 </web-resource-collection>
  <!--auth-constraint goes here if you requre authentication-->
 <user-data-constraint>
 <transport-guarantee>CONFIDENTIAL</transport-guarantee>
 </user-data-constraint>
 </security-constraint>

Which will always redirect to HTTPs.

 
5. Renew certificate:

The certificate is valid for only 90 days so we need to renew before expiry. For this, stop tomcat and type the following command:
sudo certbot renew
 
sudo -i
cd /etc/letsencrypt/live/example.com/
openssl pkcs12 -export -out bundle.pfx -inkey privkey.pem -in cert.pem -certfile chain.pem -password pass:password
 
Don't forget to use your existing password. And restart the tomcat server.

Share:

Tunnel local server to the public internet with https using Ngrok.

How to tunnel our local server to the public internet with https using Ngrok.


1. Introduction:

It seems to be daunting if we need to test our application locally over Https. Generally, when we need to listen webhook from any other service provider, testing applications locally will be difficult. In this tutorial, I will show how to tunnel the local server into the live one using ngrok.

Create an account from ngrok from which we can get tunnel auth token which we will use to get persistent Https URLs even if the outage of the internet until ngrok is running.


2. Install and set up on windows system:




Download ngrok for windows system here and unzip. After that, you will see the ngrok binary file, to run that file double click it. Make sure the path of ngrok, you will see the command prompt as bellow.

Now you are ready to tunnel your local server port. Simply execute the following command.
ngrok.exe http 80
Here, port 80 is the server port running; you need to use the respective port of your running local server like 8080, 8090 etc.

We have successfully tunnel our local server running at port 80. We can see the two forwarding URLs which are accessible publicly. As we can see the session expires in about 8 hrs which means those URLs will be changes every 8 hrs; here we need an auth token to prevent this. Execute the following command.
ngrok.exe authtoken 5AXFH2DjGMu9NFHntjxZf_73wZyVZiKeCxrA1hwZWqX
Use your own auth token from your account instead. You can see the message in the command prompt.
Authtoken saved to configuration file: C:\Users\yourUser/.ngrok2/ngrok.yml
We will use this file to set up for multiple port tunnels. Now again run your local server port you will see the final tunneling URLs without session expires limit.

Now its time to tunnel more than one port if you need it. For this, we are using ngrok.yml config file as below:


ngrok.yml
tunnels:

 backend:

  addr: 8080
  proto: http
  
 frontend:

  addr: 8081
  proto: http
Here, I have running two applications on port 8080 and 8081. Now again run the ngrok.exe file and run the following command to start and tunnel all ports.
ngrok.exe start -all



We have successfully tunnel a multi-port server.

Note: if you get Invalid Host header error while running that URLs, start tunneling port with the following command instead:
ngrok.exe http 8080 -host-header="localhost:8080"
or
ngrok.exe http --host-header=rewrite 8080
For multiport tunnels
tunnels:

 backend:

  addr: 8080
  proto: http
  host_header: "localhost:8080"
  
 frontend:

  addr: 8081
  proto: http
  host_header: "localhost:8081"




3. Install and set up on Linux system:

Download ngrok for the Linux system here. Go to download path and simply right click and extract the file. You will see the ngrok binary file, we need to make it executable so, copy this file to usr/bin directory. 
sudo cp ~/Downloads/ngrok-stable-linux-amd64/ngrok /usr/bin/
Now type ngrok command in the terminal you can see the following output if it is successfully installed.


If it is not installed then go to the ngrok binary file path and open terminal and type command ./ngrok instead of ngrok to run and tunnel your server port.

For the persistent URLs, setup auth token using command:
ngrok authtoken 5AXFH2DjGMu9NFHntjxZf_73wZyVZiKeCxrA1hwZWqX
Use your auth token from your ngrok account, which will configure ngrok config file in your home directory.
Authtoken saved to configuration file: /home/36olearntocode/.ngrok2/ngrok.yml
If you want to tunnel single port then simply run following command and you will see the following output.
ngrok http 80


Use the respective port of your server.  

If you want to tunnel multiple ports then set up ngrok config file as:





ngrok.yml
tunnels:

 backend:

  addr: 8080
  proto: http
  
 frontend:

  addr: 8081
  proto: http
Now again run the command to start:
ngrok start -all

Output:



Note: if you get Invalid Host header error while running that URLs, start tunneling port with the following command instead:
ngrok http 8080 -host-header="localhost:8080"
or
ngrok http --host-header=rewrite 8080
For multiport tunnels
tunnels:

 backend:

  addr: 8080
  proto: http
  host_header: "localhost:8080"
  
 frontend:

  addr: 8081
  proto: http
  host_header: "localhost:8081"
We have successfully tunnel our two port 8080 and 8081 over https.
Share:

Saturday, January 22, 2022

Grails 3 Download Saved Documnets/Files (.pdf, .txt, .docx and others) Example.

How to Download different types of files using Grails 3.

If you want to use server-side file download for different types of files like pdf, txt, docx etc then there are different ways to do it.

We can use ServletOutputStream object for it as below:

    def download(){
            def filePath = "/opt/tomcat/webapps/savedFile/filename.pdf" //I am saving files on tomcat.
            def file = new File(filePath)
            if (file.exists()){
                response.setContentType("application/octet-stream")
                response.setHeader("Content-disposition", "filename=${file.getName()}")
                response.outputStream << file.bytes
            }else {
                //handle file not found messages.
            }
}
Here, contentType is "application/octet-stream" for all types of file. If you want to specified for specific one set contentType for specific one.
                response.setContentType("application/pdf")
Or you can do simply like this:

    def download(){
            def filePath = "/opt/tomcat/webapps/savedFile/filename.pdf" //I am saving files on tomcat.
            def file = new File(filePath)
            if (file.exists()){
                response.setContentType("application/octet-stream")
                response.setHeader("Content-disposition", "filename=${file.getName()}")
                response.outputStream << file.newInputStream()
            }else {
                //handle file not found messages.
            }
}
def download(){
            def filePath = "/opt/tomcat/webapps/savedFile/filename.pdf" //I am saving files on tomcat.
            def file = new File(filePath)
            if (file.exists()){
                response.setContentType("application/octet-stream")
                response.setHeader("Content-disposition", "filename=${file.getName()}")
                def outputStream = response.getOutputStream()
                outputStream << file.bytes
                outputStream.flush()
                outputStream.close()
            }else {
                //handle file not found messages.
            }
}
But in grails 3 latter version while deploying the war file to external tomcat(tomcat 7) server then we might get some class not found issue while downloading files.
Error 500: Internal Server Error
URI
/patient/download
Class
java.lang.ClassNotFoundException
Message
Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: javax/servlet/WriteListener
Caused by
javax.servlet.WriteListener
In order to solve this issue, we need to make the controller's action wrap with @GrailsCompileStatic annotation.
import grails.compiler.GrailsCompileStatic

@GrailsCompileStatic
def download(){
            def filePath = "/opt/tomcat/webapps/savedFile/filename.pdf" //I am saving files on tomcat.
            def file = new File(filePath)
            if (file.exists()){
                response.setContentType("application/octet-stream")
                response.setHeader("Content-disposition", "filename=${file.getName()}")
                def outputStream = response.getOutputStream()
                outputStream << file.bytes
                outputStream.flush()
                outputStream.close()
            }else {
                //handle file not found messages.
            }
}
Share: