• CodeIgniter

    CodeIgniter Error Message

    Cookie “ci_session” will be soon rejected because it has the “sameSite” attribute set to “none” or an invalid value, without the “secure” attribute. To know more about the “sameSite“ attribute, read https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie/SameSite
    

    Pada file config perlu menggunakan konfigurasi sebagai berikut:

    public $cookieSecure  = true; 
  • Android

    Android realtime chat dengan menggunakan Firebase Realtime Database

    Pada artikel kali ini, saya akan membuat realtime chat yang sederhana dengan menggunakan Firebase Realtime Database. Firebase Realtime Database adalah database yang di-host di cloud. Data disimpan sebagai JSON dan disinkronkan secara realtime ke setiap klien yang terhubung. Ketika membuat aplikasi cross-platform dengan SDK Android, iOS, dan JavaScript, semua klien akan berbagi sebuah instance Realtime Database dan menerima update data terbaru secara otomatis.

    Langkah pertama yang perlu dilakukan adalah membuat firebase project pada:

    https://console.firebase.google.com

    Setelah project berhasil dibuat, selanjutnya adalah membuat database pada firebase.

    Ganti permission pada database, dengan cara buka menu Develop > Database. Pada dropdown pilih Realtime Database kemudian klik tab Rules. Edit rules menjadi:

    {
      "rules": {
        ".read": true,
        ".write": true
      }
    }

    Langkah berikutnya adalah membuat Project baru pada Android Studio, dengan cara File -> New -> New Project.

    Pada aplikasi android yang dibuat, akan dibagi menjadi tiga halaman utama, yaitu halaman untuk join. Yang kedua adalah halaman untuk membuat room. Dan yang terakhir adalah halaman untuk chatting.

    Klik kanan pada project -> Activity -> Empty Activity. Kemudian beri nama JoinActivity.

    Jangan lupa jadikan JoinActivity ini menjadi main activity dengan cara buka AndroidManifest.xml. Tambahkan intent-filter pada konfigurasi JoinActivity.

    <activity
        android:name=".ui.login.LoginActivity"
        android:label="@string/title_activity_login">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    Buka JoinActivity kemudian buat kode seperti berikut ini:

    package org.akhal.example.qchat;
    
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import com.google.firebase.database.ChildEventListener;
    import com.google.firebase.database.DataSnapshot;
    import com.google.firebase.database.DatabaseError;
    import com.google.firebase.database.DatabaseReference;
    import com.google.firebase.database.FirebaseDatabase;
    
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    
    public class ChatActivity extends AppCompatActivity {
    
        private Button btnSend;
        private EditText etMessage;
        private TextView tvMessage;
        private DatabaseReference rootDb;
        private String username, room;
        private String tempKey;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_chat);
    
            btnSend = findViewById(R.id.btn_send);
            etMessage = findViewById(R.id.et_message);
            tvMessage = findViewById(R.id.tv_message);
    
            QPrefs qPrefs = new QPrefs(this);
            username = qPrefs.getUsername();
            room = qPrefs.getRoom();
            setTitle("Room - "+room);
    
            rootDb = FirebaseDatabase.getInstance().getReference().child(room);
    
            btnSend.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
    
                    Map<String, Object> map = new HashMap<String, Object>();
                    tempKey = rootDb.push().getKey();
                    rootDb.updateChildren(map);
    
                    DatabaseReference msgRoot = rootDb.child(tempKey);
                    Map<String, Object> map2 = new HashMap<String, Object>();
                    map2.put("name",username);
                    map2.put("msg",etMessage.getText().toString());
                    msgRoot.updateChildren(map2);
                }
            });
    
            rootDb.addChildEventListener(new ChildEventListener() {
                @Override
                public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                    append_chat_conversatin(dataSnapshot);
                }
    
                @Override
                public void onChildChanged(DataSnapshot dataSnapshot, String s) {
                    append_chat_conversatin(dataSnapshot);
                }
    
                @Override
                public void onChildRemoved(DataSnapshot dataSnapshot) {
    
                }
    
                @Override
                public void onChildMoved(DataSnapshot dataSnapshot, String s) {
    
                }
    
                @Override
                public void onCancelled(DatabaseError databaseError) {
    
                }
            });
    
        }
    
        private void append_chat_conversatin(DataSnapshot dataSnapshot) {
            Iterator i = dataSnapshot.getChildren().iterator();
            while (i.hasNext()){
                String msg = (String) ((DataSnapshot)i.next()).getValue();
                String username = (String) ((DataSnapshot)i.next()).getValue();
                tvMessage.append(username + " : "+msg +"\n");
    
    
            }
        }
    }
    

    Untuk activiy_join.xml buat menjadi seperti berikut:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingBottom="@dimen/activity_vertical_margin">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:gravity="center"
            android:orientation="vertical">
    
            <EditText
                android:id="@+id/et_join"
                android:layout_width="300dp"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:hint="username"/>
    
            <Button
                android:id="@+id/btn_join"
                android:layout_marginTop="20dp"
                android:layout_width="200dp"
                android:layout_height="wrap_content"
                android:text="Join"/>
    
        </LinearLayout>
    </LinearLayout>

    Kemudian buka MainActivity dan tambahkan kode sehingga menjadi seperti di bawah ini:

    package org.akhal.example.qchat;
    
    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.ArrayAdapter;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.ListView;
    import android.widget.TextView;
    import androidx.appcompat.app.AppCompatActivity;
    import com.google.firebase.database.DataSnapshot;
    import com.google.firebase.database.DatabaseError;
    import com.google.firebase.database.DatabaseReference;
    import com.google.firebase.database.FirebaseDatabase;
    import com.google.firebase.database.ValueEventListener;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;
    
    public class MainActivity extends AppCompatActivity {
    
        private Button btnRoom;
        private EditText etRoom;
        private ListView lvRoom;
        private Context context;
        private DatabaseReference dbRoot = FirebaseDatabase.getInstance().getReference().getRoot();
        private ArrayAdapter<String> arrayAdapter;
        private ArrayList<String> list_of_rooms = new ArrayList();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            context = this;
            btnRoom = findViewById(R.id.btn_room);
            etRoom = findViewById(R.id.et_room);
            lvRoom = findViewById(R.id.lv_room);
    
            arrayAdapter = new ArrayAdapter<String>(context,android.R.layout.simple_list_item_1,list_of_rooms);
            lvRoom.setAdapter(arrayAdapter);
    
            btnRoom.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put(etRoom.getText().toString(),"");
                    dbRoot.updateChildren(map);
                }
            });
    
            dbRoot.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    Set<String> set = new HashSet<String>();
                    Iterator i = dataSnapshot.getChildren().iterator();
                    while ( i.hasNext()) {
                        set.add(((DataSnapshot)i.next()).getKey());
                    }
                    list_of_rooms.clear();
                    list_of_rooms.addAll(set);
                    arrayAdapter.notifyDataSetChanged();
                }
    
                @Override
                public void onCancelled(DatabaseError databaseError) {
    
                }
            });
    
            lvRoom.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                    QPrefs qPrefs = new QPrefs(context);
                    qPrefs.setRoom(((TextView)view).getText().toString());
                    Intent I = new Intent(getApplicationContext(), ChatActivity.class);
                    startActivity(I);
                }
            });
    
        }
    }
    

    Untuk activity_main.xml menjadi seperti berikut:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin">
    
        <ListView
            android:id="@+id/lv_room"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_alignParentRight="true"
            android:layout_alignParentEnd="true"
            android:layout_above="@+id/et_room">
        </ListView>
    
        <EditText
            android:id="@+id/et_room"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentStart="true"
            android:layout_toStartOf="@+id/btn_room"
            android:layout_alignParentLeft="true"
            android:layout_toLeftOf="@+id/btn_room" />
    
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Room"
            android:id="@+id/btn_room"
            android:layout_gravity="right"
            style="?android:attr/borderlessButtonStyle"
            android:layout_alignParentBottom="true"
            android:layout_alignParentEnd="true"
            android:layout_alignParentRight="true"
            android:drawableLeft="@drawable/ic_add_black_24dp" />
    </RelativeLayout>
    

    Halaman terakhir adalah ChatActivity. Buat ChatActivity kemudian ganti code menjadi seperti berikut ini:

    package org.akhal.example.qchat;
    
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import com.google.firebase.database.ChildEventListener;
    import com.google.firebase.database.DataSnapshot;
    import com.google.firebase.database.DatabaseError;
    import com.google.firebase.database.DatabaseReference;
    import com.google.firebase.database.FirebaseDatabase;
    
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    
    public class ChatActivity extends AppCompatActivity {
    
        private Button btnSend;
        private EditText etMessage;
        private TextView tvMessage;
        private DatabaseReference rootDb;
        private String username, room;
        private String tempKey;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_chat);
    
            btnSend = findViewById(R.id.btn_send);
            etMessage = findViewById(R.id.et_message);
            tvMessage = findViewById(R.id.tv_message);
    
            QPrefs qPrefs = new QPrefs(this);
            username = qPrefs.getUsername();
            room = qPrefs.getRoom();
            setTitle("Room - "+room);
    
            rootDb = FirebaseDatabase.getInstance().getReference().child(room);
    
            btnSend.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
    
                    Map<String, Object> map = new HashMap<String, Object>();
                    tempKey = rootDb.push().getKey();
                    rootDb.updateChildren(map);
    
                    DatabaseReference msgRoot = rootDb.child(tempKey);
                    Map<String, Object> map2 = new HashMap<String, Object>();
                    map2.put("name",username);
                    map2.put("msg",etMessage.getText().toString());
                    msgRoot.updateChildren(map2);
                }
            });
    
            rootDb.addChildEventListener(new ChildEventListener() {
                @Override
                public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                    append_chat_conversatin(dataSnapshot);
                }
    
                @Override
                public void onChildChanged(DataSnapshot dataSnapshot, String s) {
                    append_chat_conversatin(dataSnapshot);
                }
    
                @Override
                public void onChildRemoved(DataSnapshot dataSnapshot) {
    
                }
    
                @Override
                public void onChildMoved(DataSnapshot dataSnapshot, String s) {
    
                }
    
                @Override
                public void onCancelled(DatabaseError databaseError) {
    
                }
            });
    
        }
    
        private void append_chat_conversatin(DataSnapshot dataSnapshot) {
            Iterator i = dataSnapshot.getChildren().iterator();
            while (i.hasNext()){
                String msg = (String) ((DataSnapshot)i.next()).getValue();
                String username = (String) ((DataSnapshot)i.next()).getValue();
                tvMessage.append(username + " : "+msg +"\n");
    
    
            }
        }
    }
    

    Dan activity_chat.xml menjadi seperti berikut:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        android:orientation="vertical"
        android:weightSum="1">
    
        <ScrollView
            android:id="@+id/sv_message"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:layout_alignParentTop="true"
            android:layout_alignParentStart="true"
            android:layout_alignParentLeft="true">
    
            <TextView
                android:id="@+id/tv_message"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceMedium" />
        </ScrollView>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:weightSum="1">
            <EditText
                android:id="@+id/et_message"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignTop="@+id/button"
                android:layout_alignParentStart="true"
                android:layout_toStartOf="@+id/button"
                android:layout_weight="1"
                android:layout_alignParentLeft="true"
                android:layout_toLeftOf="@+id/button" />
    
            <Button
                android:id="@+id/btn_send"
                android:layout_width="56dp"
                android:layout_height="wrap_content"
                style="?android:attr/borderlessButtonStyle"
                android:drawableLeft="@drawable/ic_send_black_24dp"
                android:layout_alignParentBottom="true"
                android:layout_alignParentEnd="true"
                android:layout_alignParentRight="true" />
    
        </LinearLayout>
    
    </LinearLayout>
    

    Langkah terakhir adalah membuat shared preferences. Shared preferences digunakan untuk menyimpan username yang digunakan dan room yang dipilih. Buat file dengan nama QPrefs.

    package org.akhal.example.qchat;
    
    import android.content.Context;
    import android.content.SharedPreferences;
    
    /**
     * Created by Akhal on 2020/06/3.
     */
    public class QPrefs {
    
        private SharedPreferences pref;
    
        public QPrefs(Context context) {
            pref = context.getSharedPreferences("qpref", context.MODE_PRIVATE);
        }
    
        public void setUsername(String username) {
            pref.edit().putString("username", username).commit();
        }
    
        public String getUsername() {
            return  pref.getString("username", "");
        }
    
        public void setRoom(String room) {
            pref.edit().putString("room", room).commit();
        }
    
        public String getRoom() {
            return  pref.getString("room", "");
        }
    }
    

    Jika sudah selesai, jalankan aplikasi yang dibuat.

  • Java

    Java Native Interface

    Java Native Interface (JNI) merupakan framework yang mengizinkan kode Java untuk memanggil native language seperti C, C+, maupun asemby. JNI dibutuhkan untuk mengoptimalkan performa pada Java.

    Install terlebih dahulu tools yang diperlukan:

    1. JDK dan JRE
    2. Java IDE, pada kali ini digunakan Netbeans IDE 11.2.
    3. C++ IDE, pada kali ini digunakan Qt.

    Langkah pertama, buat project pada Netbeans.

    Buat Java class dengan nama file HelloJNI.java

    Buat kode sebagai berikut:

    public class HelloJNI {
        
        static {
            System.loadLibrary("HelloJNI");
        }
        
        private native void haii();
        
        public static void main(String[] args) {
          new HelloJNI().haii(); 
       }
        
    }

    Static initialer dibutuhkan untuk mengambil library native, menggunakan System.loadLibrary(). Selanjutnya adalah menghubungkan native method yang terdapat pada native library ke Java. Pada contoh di atas dibuat method dengan nama haii(). Untuk mencobanya dibuat fungsi utama main pada kelas di atas.

    Langkah selanjutkan adalah compile program Java tersebut.

    Jika berhasil dicompile, selanjutnya membuat header file untuk C/C++ dengan menggunakan bantuan command javah.

    javah -classpath target/classes org.akhal.example.hellojni.HelloJNI

    Jika berhasil, maka akan dihasilkan file dengan nama org_akhal_example_hellojni_HelloJNI.h

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class org_akhal_example_hellojni_HelloJNI */
    
    #ifndef _Included_org_akhal_example_hellojni_HelloJNI
    #define _Included_org_akhal_example_hellojni_HelloJNI
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     org_akhal_example_hellojni_HelloJNI
     * Method:    haii
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_org_akhal_example_hellojni_HelloJNI_haii
      (JNIEnv *, jobject);
    
    #ifdef __cplusplus
    }
    #endif
    #endif

    Selanjutnya buat program C/C++. Pada contoh ini digunakan Qt Creater.

    Tambahkan QMAKE_LFLAGS pada file .pro

    QMAKE_LFLAGS += -Wl,--add-stdcall-alias

    Tambahkan juga include path untuk Java pada file .pro

    INCLUDEPATH += "C:/Program Files (x86)/Java/jdk1.8.0_251/include/"
    INCLUDEPATH += "C:/Program Files (x86)/Java/jdk1.8.0_251/include/win32"

    Replace isi file org_akhal_example_hellojni_hellojni.h dengan kode hasil generate dari javah. Kemudian buat isi program untuk method haii() pada file org_akhal_example_hellojni_hellojni.cpp

    #include "org_akhal_example_hellojni_hellojni.h"
    
    JNIEXPORT void JNICALL Java_org_akhal_example_hellojni_HelloJNI_haii(JNIEnv *env, jobject thisObj) {
       printf("Hello World!\n");
       return;
    }

    Kemudian build program sehingga dihasilkan file HelloJNI.dll. Copy file tersebut ke folder project Netbeans.

    Langkah terakhir tes dengan cara menjalankan program Java. Akah diperoleh output seperti pada gambar di bawah ini:

  • PHP

    PHP stdClass to Array

    PHP stdClass to Array

    function objectToArray($d) {
        if (is_object($d)) {
            // Gets the properties of the given object
            // with get_object_vars function
            $d = get_object_vars($d);
        }	
        if (is_array($d)) {
            /*
            * Return array converted to object
            * Using __FUNCTION__ (Magic constant)
            * for recursive call
            */
            return array_map(__FUNCTION__, $d);
        }
        else {
            // Return array
            return $d;
        }
    }
    

    PHP Array to stdClass

    function arrayToObject($d) {
        if (is_array($d)) {
            /*
            * Return array converted to object
            * Using __FUNCTION__ (Magic constant)
            * for recursive call
            */
            return (object) array_map(__FUNCTION__, $d);
        }
        else {
            // Return object
            return $d;
        }
    }
    
  • Linux

    OpenVPN

    Install OpenVPN Server

    Download script untuk install OpenVPN:

    curl -O https://raw.githubusercontent.com/angristan/openvpn-install/master/openvpn-install.sh 
    chmod +x openvpn-install.sh

    Jalankan script:

    ./openvpn-install.sh

    Selesai.

    Untuk konfigurasi OpenVPN dan firewall dapat dilihat di:

    /etc/rc.local -> Firewall 
    /etc/openvpn/server/server.conf -> Konfigurasi OpenVPN

    Jika ingin menambahkan user lain, dapat menjalankan ulang script di atas.

    Command OpenVPN Server

    sudo systemctl stop openvpn@server # <--- stop server
    sudo systemctl start openvpn@server # <--- start server
    sudo systemctl restart openvpn@server # <--- restart server
    sudo systemctl status openvpn@server # <--- get server status

    Install OpenVPN Client

    Install package.

    sudo apt install openvpn

    Copy file .ovpn ke directory /etc/openvpn/, kemudian rename dengan extension .conf

    sudo systemctl start openvpn@client  # <--- start client

    IP forwarding pada Client

    Buka file /etc/sysctl.conf

    Uncomment baris #net.ipv4.ip_forward=1

    Simpan file

    Reboot

  • macOS

    Homebrew

    Homebrew adalah open-source software package management system yang memudahkan instalasi perangkat lunak pada sistem operasi macOS dan Linux.

    Install command Line Tools.

    xcode-select --install

    Install homebrew:

    /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

    Untuk menghapus homebrew dapat menggunakan command berikut ini.

    MacOS Catalina, macOS Big Sur, and MacOS Mojave:

    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall.sh)"

    MacOS High Sierra, Sierra, El Capitan, dan versi sebelumnya:

    ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall)"

    Pada homebrew, terdapat data collection yang mengumpulkan data-data installation, build error, dan operating system version melalui Google Analytics. Jika tidak ingin mematikan fitur ini, dapat mendisabelnya dengan cara:

    brew analytics off

  • Java

    Install Maven Local Repository

    Download Apache Maven disini.

    Tambahkan maven ke path pada Environment Variables.

    Jalankan command berikut ini:

    mvn install:install-file -Dfile=<path-to-file> -DgroupId=<group-id> -DartifactId=<artifact-id> -Dversion=<version> -Dpackaging=<packaging> 

    Jika file JAR di hasilkan oleh Apache Maven:

    mvn install:install-file -Dfile=<path-to-file> 

    Jika menggunakan pom-file:

    mvn install:install-file -Dfile=<path-to-file> -DpomFile=<path-to-pomfile> 

    Keterangan:
    <path-to-file> lokasi file jar
    <group-id> nama group id (misal: org.akhal)
    <artifact-id> nama library (misal: kbbi)
    <version> versi library
    <packaging> jenis packaging (misalkan: jar)

  • Linux

    Menjalankan Program Java sebagai Service pada Ubuntu

    Buat sebuah Service

    sudo nano /etc/systemd/system/myjava.service

    Copy/paste kode berikut ini ke dalam file myjava.service

    [Unit]
    Description=My Java Service
    
    [Service]
    User=ubuntu
    # The configuration file application.properties should be here:
    
    #change this to your workspace
    WorkingDirectory=/home/ubuntu/workspace
    
    #path to executable. 
    #executable is a bash script which calls jar file
    ExecStart=/home/ubuntu/workspace/start
    
    SuccessExitStatus=143
    TimeoutStopSec=10
    Restart=on-failure
    RestartSec=5
    
    [Install]
    WantedBy=multi-user.target

    Buat file Bash Script untuk memanggil Service

    nano /home/ubuntu/workspace/start

    Copy/paste kode berikut:

    #!/bin/sh 
    /usr/bin/java -jar myjava.jar

    Start Service

    sudo systemctl enable myjava.service
    sudo systemctl start myjava.service
  • Linux

    Command SSH on CentOS

    Install

    sudo yum install openssh-server openssh-clients

    Configuration

    sudo nano /etc/ssh/sshd_config

    Create ssh keygen

    ssh-keygen -t rsa

    Start

    sudo systemctl start sshd.service

    Stop

    sudo systemctl stop sshd.service

    Restart

    sudo systemctl restart sshd.service

    Enable auto start

    sudo systemctl enable sshd.service

    Disable auto start

    sudo systemctl disable sshd.service
  • macOS

    Install Apache, MySQL, PHP on macOS Mojave 10.14

    Pada macOS Mojave, aplikasi apache sudah terinstall sebagai program bawaan. Yang perlu dilakukan hanya menjalankannya dengan command:

    sudo apachectl start 

    Command berikut untuk mematikan apache:

     sudo apachectl stop 

    Command berikut untuk me-restart apache:

     sudo apachectl restart 

    Jika ingin mengetahui versi apache yang terinstall dapat menggunakan command berikut:

     httpd -v 

    Secara default, system document root untuk web server dapat dilihat di:

     /Library/WebServer/Documents/ 

    Selain menggunakan lokasi yang ada pada sistem, dapat juga menggunakan lokasi yang ada pada user (User Level Root) yang ada pada folder Sites. Tambahkan username.conf pada directory:

     /etc/apache2/users/ 

    Buka terminal, kemudian ketikkan command berikut:

     cd /etc/apache2/users 
     sudo nano username.conf 

    nama file username.conf sesuaikan dengan nama username yang digunakan. Kemudian tambahkan kode berikut:

    <Directory "/Users/username/Sites/"> 
    AllowOverride All
    Options Indexes MultiViews FollowSymLinks
    Require all granted
    </Directory> 

    Dengan konfigurasi file permission:

     -rw-r--r--   1 root  wheel  298 Jun 28 16:47 username.conf 

    Jika belum seperti di atas, file permission dapat diganti dengan menggunakan perintah:

     sudo chmod 644 username.conf 

    Langkah selanjutnya, buka file httpd.conf, kemudian edit konfigurasi untuk beberapa module.

     sudo nano /etc/apache2/httpd.conf 

    Pastikan module berikut dalam kondisi uncomment.

    LoadModule authz_core_module libexec/apache2/mod_authz_core.so
    LoadModule authz_host_module libexec/apache2/mod_authz_host.so
    LoadModule userdir_module libexec/apache2/mod_userdir.so
    LoadModule include_module libexec/apache2/mod_include.so
    LoadModule rewrite_module libexec/apache2/mod_rewrite.so

    Jika menggunakan php, uncomment module berikut:

    LoadModule php7_module libexec/apache2/libphp7.so

    Jika ingin menggunakan user home directories, uncomment baris berikut:

    Include /private/etc/apache2/extra/httpd-userdir.conf 

    Langkah berikutnya, buka config lain untuk apache:

    sudo nano /etc/apache2/extra/httpd-userdir.conf 

    Uncomment baris berikut:

    Include /private/etc/apache2/users/*.conf 

    Kemudian restart apache server:

    sudo apachectl restart 

    Untuk level system document root, dapat dilihat di url:

    http://localhost/ 

    Untuk level user document root, dapat dilihat di url:

    http://localhost/~username/ 

    Jika ingin mengijinkan .htaccess untuk meng-override default setting, dapat menggunakan cara berikut:

    sudo nano /etc/apache2/httpd.conf 

    Dan jangan lupa, uncomment module mod_rewrite.

    LoadModule rewrite_module libexec/apache2/mod_rewrite.so 

    Untuk melihat konfigurasi dari apache server, dapat membuat file phpinfo.php pada document root.

    <?php phpinfo(); ?> 

    Secara default, MySQL tidak ter-install sebagai aplikasi bawaan dari macOS Mojave, sehingga perlu di-install secara manual. Aplikasi MySQL dapat diunduh disini.

    Setelah berhasil diunduh, install MySQL dan ikuti langkah-langkahnya sampai instalasi selesai.

    Setelah instalasi MySQL selesai, langkah berikutnya mengganti password user root untuk MySQL.

    Stop MySQL

    sudo /usr/local/mysql/support-files/mysql.server stop 

    Start MySQL dalam safe mode:

    sudo mysqld_safe --skip-grant-tables 

    Buka tab terminal baru, kemudian login ke MySQL dengan user root, kemudian ganti password untuk root.

    mysql -u root 
    FLUSH PRIVILEGES; 
    ALTER USER 'root'@'localhost' IDENTIFIED BY 'new_password'; 
    \q 

    Start MySQL

    sudo /usr/local/mysql/support-files/mysql.server start 

    Connect PHP and MySQL

    mkdir /var/mysql 
    ln -s /tmp/mysql.sock /var/mysql/mysql.sock
    sudo apachectl restart