Migrating to Obsidian

Recently someone released Foam for VSCode on Obsidian, it led me down a rabbit hole of Second brain and Zettelkasten method. In short: it’s an enhanced mindmap with text, images and link between articles

Sound similar to a wiki? Yes. Shall I try out this new thing? Also yes.

So I started to Migrate all my notes to Obsidian, an excellent implementation of this idea (and it’s free for personal use).

My notes a scattered between SimpleNote, Google Keep and OneNote

Migrating from SimpleNote

You can export your notes to HTML from the web app. Then convert HTML to MD with pandoc

Migrating from Google Keep

You can use google Takeout to export your Keep notes to a bunch of HTML files, then use pandoc. You may need to edit the resulting md files a little bit. VS Code is an excellent tool for this

Migrating from OneNote

This is where most of my notes are, and is the most involved. You need

  • A Windows machine
  • OneNote Office Version (not the Windows Store version)

Use this script https://github.com/rab-bit/ConvertOneNote2MarkDown4Obsidian and follow the instruction. This is an updated version of the original script here with various bugs fixed.

TIL: Java stuff

Java Lambda as parameter

First you need an interface

    private interface Ec2Operation {
        void apply(Ec2Client ec2, String... instanceId);
    }

Then declare the operation (note that you don’t need to define “apply”, just use the interface name. “apply” can actually be anything, as you’ll call it later

Ec2Operation startInstance = (ec2, instances) -> {
StartInstancesRequest request = StartInstancesRequest.builder()
.instanceIds(instances)
.build();
ec2.startInstances(request);
};

Then use it with the interface as a signature, call the function you named

private RequestResult executeEc2Operation(Ec2Operation operation) {
    operation.apply(client, instances);
}

Then call the lambda as parameter in a third function

    public RequestResult start() {
        return executeEc2Operation(startInstance);
    }

Having to declare the interface explicitly makes it much more verbose than Javascript. However you get the benefit of a strong type.

Scala and Go’s approach is probably the best of both worlds: you just need to declare the type in the lambda itself.

SSH library for Java

JSCH is the first result in Google. However it hasn’t been updated in along time and doesn’t support newer algorithms.

SSHJ seems to be a more modern choice. It’s on github too!

TIL: When finally Is Executed

In short, finally overrides some of the “expected” behavior like returning from the try – catch block, allowing you to free up resources / do clean up regardless of whether there was an error or not

No Exception Is Thrown

When the try block completes, the finally block is executed, even if there was no exception:

try {
    System.out.println("Inside try");
} finally {
    System.out.println("Inside finally");
}

In this example, we aren’t throwing an exception from the try block. Thus, the JVM executes all code in both the try and finally blocks.

This outputs:

Inside try
Inside finally

Exception Is Thrown and Not Handled

If there’s an exception and it is not caught, the finally block is still executed:

try {
    System.out.println("Inside try");
    throw new Exception();
} finally {
    System.out.println("Inside finally");
}

The JVM executes the finally block even in the case of an unhandled exception.

And the output would be:

Inside try
Inside finally
Exception in thread "main" java.lang.Exception

Exception Is Thrown and Handled

If there’s an exception and it is caught by the catch block, the finally block is still executed:

try {
    System.out.println("Inside try");
    throw new Exception();
} catch (Exception e) {
    System.out.println("Inside catch");
} finally {
    System.out.println("Inside finally");
}

In this case, the catch block handles the thrown exception, and then the JVM executes the finally block and produces the output:

Inside try
Inside catch
Inside finally

Method Returns from try Block

Even returning from the method will not prevent finally blocks from running:

try {
    System.out.println("Inside try");
    return "from try";
} finally {
    System.out.println("Inside finally");
}

Here, even though the method has a return statement, the JVM executes the finally block before handing the control over to the calling method.

We’ll get the output:

Inside try
Inside finally

Method Returns from catch Block

When the catch block contains a return statement, the finally block is still called:

try {
    System.out.println("Inside try");
    throw new Exception();
} catch (Exception e) {
    System.out.println("Inside catch");
    return "from catch";
} finally {
    System.out.println("Inside finally");
}

When we throw an exception from the try block, the catch block handles the exception. Though there is a return statement in the catch block, the JVM executes the finally block before handing control over to the calling method, and it outputs:

Inside try
Inside catch
Inside finally

From https://www.baeldung.com/java-finally-keyword

Daily life with Jetpack Compose part 1

How to achieve simple tasks with Jetpack Compose series. Simple tasks with plain Android stayed mostly the same with minor API changes, but there are no official documentation on this subject.

How to display a web web in a Composable

In your code

import android.webkit.WebView
import android.webkit.WebViewClient

@Composable
fun createWebView(article: Post, modifier: Modifier) {
    val context = ContextAmbient.current
    val webViewClient = WebViewClient()
    AndroidView(
        viewBlock = {
            WebView(context).apply {
                this.webViewClient = webViewClient
                this.loadUrl("https://hanquoc.kr/${article.slug}")
            }
        },
        modifier = modifier
    )
}

Don’t use the androidx version – it’s useless

How to share a URL with Jetpack Compose

In your code

import android.content.Intent

@Composable
fun ArticleView(
    article: Post
) {
    val context = ContextAmbient.current
    val shareIntent = Intent(Intent.ACTION_SEND)
    shareIntent.type = "text/plain"
    shareIntent.putExtra(Intent.EXTRA_TEXT, "https://hanquoc.kr/${article.slug}")
    shareIntent.putExtra(Intent.EXTRA_SUBJECT, article.title.rendered)
    startActivity(
        context,
        Intent.createChooser(shareIntent, null),
        null
    )
}

Open source survey application

Due to business requirements, I have forked and re-skinned a legacy PHP survey application with material design.

To give back to the community, here’s the updated source:

https://github.com/thanhphu/php-survey-builder

It contains the following improvements

  • Add material design for user-facing pages
  • Add appropriate ignore to avoid leaking credentials on source control
  • Add default user ID you can set via GET parameter when sending out mass email
  • Stricter .htaccess
  • More readable fonts