Wednesday, December 9, 2020

Restore MySql Database From Just frm and idb File

Hello,

Few days back, I encountered a situation where we needed to restore MySql Database but we only had frm and idb file. Didn't have .sql file or log file from MySql server which is very much needed when you want to restore. So here in this blog I am going to explain how you can still restore MySql Database from only frm and idb file.

First you will need a tool called dbsake which you can install with following command.

curl -s http://get.dbsake.net > dbsake

Once installed, run following command to check if it's installed properly or not. 

chmod u+x dbsake


./dbsake --version


If it shows version and all, it's installed. Now first by using this tool we will get schema of table from frm file. Run following command. 


./dbsake frmdump /PATH_TO_FRM/file.frm


It will give you create table schema like this.


CREATE TABLE `table_name` (

  `column1` int(11) NOT NULL AUTO_INCREMENT,

  `column2` varchar(255) DEFAULT NULL,

  `column3` varchar(255) DEFAULT NULL,

  PRIMARY KEY (`column1`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;


Copy it and run it in your sql editor. If you are migrating it from MySql 5 to 6 you may want to add ROW_FORMAT


CREATE TABLE `table_name` (

  `column1` int(11) NOT NULL AUTO_INCREMENT,

  `column2` varchar(255) DEFAULT NULL,

  `column3` varchar(255) DEFAULT NULL,

  PRIMARY KEY (`column1`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=compact;


Now it will create table. It's time to load data into it. 


First we will delete the table space which is idb file created. Run following command.


ALTER TABLE table_name DISCARD TABLESPACE


Now copy the old idb file and replace the existing one in your MySql server.


Now attach table space again.


ALTER TABLE table_name IMPORT TABLESPACE


That's it and now if you browse the data in table, you can see all your old rows. 

Tuesday, September 29, 2020

MySql Export / Import Large Database

Hello,

In this blog I am going to explain a trick which I recently used for Export / Import large database. 

Let me first explain the issue I faced. The database was over 250 MB. I was using MySql WorkBench to export in single self contained file. But it was breaking in between as some tables were really huge. 

So here is what I did. First in MySql WorkBench, in stead of exporting it to self contained single file, export it to Dump project folder. Here it will create sql file for each table in the folder. So in my case it created approximately 180 sql files. 

Now open terminal and go to that folder. First step here is we will concat all those files and make a single file.

Run the following command in terminal from folder where you have all the sql files.


cat *.sql  > .single_file.sql


Above command will concat all the files into one file and create that file in same folder. Now we will use this file to import into our database.


/Applications/MAMP/Library/bin/mysql -u DB_USER -p DB < .single_file.sql


That's it. With this trick you can Import / Export large database. Please note that, for this you should have terminal access to your MySql server.

Monday, September 7, 2020

Connect to Web Socket From Your Android App using OkHttp

Hello,

In this blog I am going to explain how you can connect with Web Socket from your Android App using OkHttp. This will be useful when you want to send some data real time from your Android app to Web app. 

First add following line in your build.gradle file dependencies. 

implementation 'com.squareup.okhttp3:okhttp:3.11.0'

Now let the gradle build and sync. Next we will make a class which extends WebSocketListener from OkHttp3 and a new class and name it MyWebSocketListener.java and add following code to it. 

import okhttp3.Response;

import okhttp3.WebSocket;

import okhttp3.WebSocketListener;

import okio.ByteString;

public final class MyWebSocketListener extends WebSocketListener {

    private static final int NORMAL_CLOSURE_STATUS = 5000;

    public MyWebSocketListener() {  

    }

    @Override

    public void onOpen(WebSocket webSocket, Response response) {

        webSocket.close(NORMAL_CLOSURE_STATUS, "Exit");

    }

    @Override

    public void onMessage(WebSocket webSocket, String text) {

        //String Meesage received

    }

    @Override

    public void onMessage(WebSocket webSocket, ByteString bytes) {

        //Meesage received in form of binary data

    }

    @Override

    public void onClosing(WebSocket webSocket, int code, String reason) {

        webSocket.close(NORMAL_CLOSURE_STATUS, null);

        //Closing socket

    }

    @Override

    public void onFailure(WebSocket webSocket, Throwable t, Response response) {

        t.printStackTrace();

    }

}

Now we have listener created. Let's create client and attach it to Web Socket and Listener.

val listener = MyWebSocketListener()

val webSocket =   OkHttpClient.Builder().build().newWebSocket(request, listener)


That's it, now you can use this instance to send or receive message.

Saturday, September 5, 2020

Create Secure Web Socket (WSS) with Ratchet PHP

Hello,

Recently I was working on PHP project where we I was create secure web socket which is accessible with wss:// protocol. For this I struggled for couple of hours so here in blog I am going to explain how to do that so it can save your time. 

Earlier version was not supporting WSS but later it introduced React socket server which allows SSL connection. So here are steps you need to follow. 

First add all the required classed in your php file.


use Ratchet\Server\IoServer;

use Ratchet\Http\HttpServer;

use Ratchet\WebSocket\WsServer;

use MyApp\Socket;


In above example Socket is my class file which has all listeners. After this add auto load file.

require dirname( __FILE__ ) . '/vendor/autoload.php';

Next we will create our socket app. 

$app = new \Ratchet\Http\HttpServer(
    new \Ratchet\WebSocket\WsServer(
        new \MyApp\Socket()
    )
);

Now next step is to create React Secure server.

$loop = \React\EventLoop\Factory::create();
$webSock = new \React\Socket\Server('0.0.0.0:8080', $loop);

We are using 0.0.0.0  so this socket can be connected from anywhere. 

Now lets create secure server by adding path to certificate and key

$webSock = new \React\Socket\SecureServer($webSock, $loop, [
    'local_cert' => 'CRT_PATH', 
    'local_pk'=> 'KEY_PATH', 
    'allow_self_signed' => true, 
    'verify_peer' => false
]);

Now finally we will run our server.

$webSock = new \Ratchet\Server\IoServer($app, $webSock, $loop);
$webSock->run();

That's it. It will start your server to which you can connect with WSS protocol. To test you can use WebSocket ECHO test.


Hope this helps you.

Thursday, August 20, 2020

AWS PHP SDK - Create an Entry in Route53 - Laravel

 Hello,

In this blog I will explain you how to you can create an entry in Route53 hosted zone using AWS PHP SDK. Solution I mentioned here is particularly for Laravel app, but you can still use it in any of the PHP project. 

This solution is pretty much useful when you want to make a dynamic entry in your hosted. For example a dynamic sub domain creation. 

First of all your need install couple of packages using composer. Following are the packages. 

"aws/aws-sdk-php": "^3.148",

"aws/aws-sdk-php-laravel": "~3.0",

You can either install it by adding it in composer.json file or you can install it using composer require. 

Once the installation is done, follow the steps mentioned in below URL. 

https://github.com/aws/aws-sdk-php-laravel

Once installation is done. You need to add following keys in your env file.

AWS_ACCESS_KEY_ID

AWS_SECRET_ACCESS_KEY

AWS_REGION (default = us-east-1)

Set the values in above keys from your AWS account. That's it your AWS SDK is ready. Now add following line your controller where you want to have logic for adding value in Route53

use Aws\Route53\Route53Client;

use Aws\Common\Credentials\Credentials;

Now next step is to create a client

$client = Route53Client::factory(array(

            'credentials' => config('aws.credentials'),

            'region' => config('aws.region'),

            'version' => config('aws.version'),

)); 

After client is created we will use changeResourceRecordSets to create an entry.

$result = $client->changeResourceRecordSets(array(

            // HostedZoneId is required

            'HostedZoneId' => 'YOUR_HOSTED_ZONE_ID',

            // ChangeBatch is required

            'ChangeBatch' => array(

                'Comment' => 'string',

                // Changes is required

                'Changes' => array(

                    array(

                        // Action is required

                        'Action' => 'CREATE',

                        // ResourceRecordSet is required

                        'ResourceRecordSet' => array(

                            // Name is required

                            'Name' => 'YOUR_VALUE',

                            // Type is required

                            'Type' => 'CNAME', //A, CANME

                            'TTL' => 600,

                            'ResourceRecords' => array(

                                array(

                                    // Value is required

                                    'Value' => 'YOUR_VALUE', //IP address or load balancer.

                                ),

                            ),

                        ),

                    ),

                ),

            ),

        ));

That's it and it will create an entry in Route53 hosted zone. 

Tuesday, August 4, 2020

Android Build Error - The Crashlytics build ID is missing

Hello,

Recently I faced a very strange issue in one of my android app. We were using Fabric IO for crash analytics earlier in the app and since now it's already merged with Firebase Analytics. we need to update the app. 

I removed Firebase maven repository and removed all plugins from build gradle file and removed Fabric code from everywhere. And build was successful. After that I followed all the instructions on getting started page of Firebase and crash analytics and build was successful.  And then problem started. Once we run the app, it crashes and shows following error in Logcat. 

"The Crashlytics build ID is missing. This occurs when Crashlytics tooling is absent from your app's build configuration. Please review Crashlytics onboarding instructions and ensure you have a valid Crashlytics account

Now it seems there is an issue with Firebase crash analytics account so I regenerated the google service json file add updated in project. But it didn't help. 

Searched on Google, answers suggest to put back Fabric plugin again in gradle file. Which does not make any sense to me. Since Fabric is out dated, why do we need to add it again. 

Finally after 2 days I was able to solve the problem. Here is the solution

Remove google service json file. Use Firebase assistant and connect with your account again. Select the project and it again generate google service json file. Keep link to fabric io repository in top level gradle file.

maven { url 'https://maven.fabric.io/public' }

I don't know how it worked but it works and I really don't know the reason of why it didn't work and why it started working after above solution. But it does solve the problem. 

If anyone who is reading this blog, knows the reason please put in comment. 

Sunday, March 22, 2020

Angular 7 App ng build Works But ng build --prod Gives Error

Hello,

Recently I was trying to generate production build of one of our older Angular app which was built on Angular 6 and later upgraded to Angular 7. When we run ng build it works fine but when we run ng build --prod it gives so many errors.

Here in this blog I am going to explain what are those errors and how I solved it.

Problem 1 : Strict Parameter checking for function.

There were few events and handler defined in the app where there were parameter mismatch. For example in html file we have following event.

<componentName (event)="eventHandler($event)"></componentName >

And in component TS file event handler was defined like this

eventHandler() {
}

As you can see from html file it was passing $event param but on handler param was not mentioned. So make sure that your function signature and function declaration matches.

Problem 2 : Duplicate Declaration of Components

By mistake we have duplicate declaration of components in both App module and and other child modules of the app. Make sure you either declare all your components to app module or if you are defining it into sub module then make sure you remove it from app module.

Problem 3 : Cannot read property 'moduleType' of undefined

When you face above issue please check your app module by mistake you may have defined following line twice in your app module.

platformBrowserDynamic().bootstrapModule(AppModule);

It's like you are trying to bootstrap your Angular app twice and it gives above error. So try to avoid it.

Problem 4 : Enable IVY

In Angular 7 by default IVY is disabled hence even if you generate production build you app size it bit large. To enable IVY add following line to your tsconfig.json file.

"angularCompilerOptions": {
    "enableIvy": true
}

Hope this blog post helps you.

Laravel App Connect and Emit to Socket.io

Hello,

Recently in one of the project I was working on we have socket.io server created using NodeJS and there were couple of Angular applications and android applications connects with it. However there was a requirement to connect with socket from Laravel app and emit the event.

Actually there was a form in Laravel app on submit of Form we have to notify the socket and socket further notify all the clients connected to it. In this blog I am going to mention how we solved this.

We all know Laravel by default comes with integration of Pusher we could have used it. But since Socket.io is free so we consider to use Socket.io.

Let's go step by step and understand how to connect with Socket.io

Step 1

Create new folder socket in your app directory of Laravel app.

Step 2

Copy following class in to app/Socket folder and rename it to SocketIO.php

https://github.com/psinetron/PHP_SocketIO_Client

There are many PHP socket IO client is available but we used above one. You can choose either one of your choice.

Step 3

Connect and emit to socket. In your controller file where you want to emit the event. Add following code.

$socketIO = new SocketIO();
$returnValue = $socketIO->send('YOUR_URL', YOUR_PORT, 'YOUR_EVENT',json_encode(YOUR_PHP_ARRAY))

For this add following line to top of your controller.

use App\socket\SocketIO;

That's it and now you can connect with socket and emit event to it.

Socket.io Not Working on Android 9 (API 28)

Hi,

Recently in one of the project we faced a situation where we have used socket.io on backend and Android app connects to it. Socket.io was using http protocol for testing. It worked fine in older android versions but faced an issue in Android 9 and above where socket was connected but emit was not getting on server.

After couple of hours struggle finally found the problem. The problem was socket io was using http protocol and it's clearText HTTP request and it is banned in recent android version considering security reasons.

In earlier android version by default clearText is set as true but in later version default value is false. That means android components like HTTP and FTP and classes DownloadManager, and MediaPlayer can not use HTTP.

To over come this issue and allow socket to connect with HTTP protocol you have to allow clearText traffic on app level and for that you have to add following attribute in Application tag of your AndroidManifest.xml

<application
        android:usesCleartextTraffic="true">
.....
</application>

Once you add this to your manifest file, your socket emit will start working and you can still use HTTP with your socket.

Please note that since it was testing app we used HTTP based socket. However in production you should always use HTTPs protocol.

Hope this helps you.