Ron and Ella Wiki Page

Extremely Serious

Page 27 of 34

ThreadPoolExecutor with ArrayBlockingQueue and Custom Thread Name

Create an implementation of ThreadFactory to create a thread with custom name for ThreadPoolExecutor as follows:

class MyThreadFactory implements ThreadFactory {
    private AtomicLong threadCounter;

    private MyThreadFactory() {
        threadCounter = new AtomicLong();
    }

    @Override
    public Thread newThread(Runnable runnable) {
        var thread=new Thread(runnable);
        thread.setName(String.join("-","my-thread",
                String.valueOf(threadCounter.incrementAndGet())));
        return thread;
    }
}

The preceding class will generate a thread with the name starting with my-thread. Use the instance of this class in constructing the ThreadPoolExecutor as follows:

var executor = new ThreadPoolExecutor(2, 4, 60L, TimeUnit.SECONDS,
        new ArrayBlockingQueue<>(100), new MyThreadFactory(), 
        new ThreadPoolExecutor.CallerRunsPolicy());

The preceding declaration creates an instance of ThreadPoolExecutor with 2 core threads, 4 maximum threads, 60 seconds keep alive and supports 100 items in the queue. The queue size is defined by the instance of ArrayBlockingQueue class.

Start all the core threads as follows:

executor.prestartAllCoreThreads();

Using a profiling tool we can search for all the threads whose names starts with my-thread like the following screenshot:

Don't forget to call any shutdown/terminate methods when done using the executor.

Getting a Resource using ModuleLayer

If the resource and the module are known, we can use the ModuleLayer to access it like the following snippet.

ModuleLayer.boot().findModule(<MODULE_NAME>).ifPresent(___module -> {
    try {
        var modResource = ___module.getResourceAsStream(<RESOURCE_NAME>);
    } catch (IOException e) {
        e.printStackTrace();
    }
});

Where:

MODULE_NAME -> the name of the module that has the resource.
RESOURCE_NAME -> the resource of interest.

Squashing Commits Before Pushing a Branch into a Git Upstream

Pre-requisite

  • Git is installed locally.

Procedures

  1. Checkout the non-master branch to be squashed.
  2. Ensure that the branch is up to date from the master.
  3. Open a terminal and change the directory to the root of checked out branch.
  4. Run the following command:
    git rebase -i master
  5. Once a text editor opens and leave the first pick alone and the subsequent picks must be replaced with squash. For example:
    From

    pick < hash1 > < message1 >
    pick < hash2 > < message2 >
    pick < hash3 > < message3 > 
    pick < hash4 > < message4 >
    

    To

    pick < hash1 > < message1 >
    squash < hash2 > < message2 >
    squash < hash3 > < message3 > 
    squash < hash4 > < message4 >
    
  6. Save the update and close the editor.
  7. Another editor will open to update the message since git is about the combine multiple commits.
  8. Update the message if necessary.
  9. Save and close the editor.
  10. If everything went fine your branch is now squashed.

Sample Usage of Java 9 Flow (Reactive Stream) API

Reactive stream is gaining traction in the mainstream programming and java has its own implementation via the Flow API. Popular reactive stream implementations are RxJava, Reactor and Akka.

import java.util.concurrent.Flow;
import java.util.concurrent.SubmissionPublisher;
import java.util.stream.IntStream;

public class Main {

    /**
     * Sample subscriber implementation.
     */
    public static class Subscriber implements Flow.Subscriber<Integer> {

        /**
         * Holds an instance of Flow.Subscription instance so that we can request what we can handle.
         */
        private Flow.Subscription subscription;

        /**
         * Tracks if the publisher was closed.
         */
        private boolean isDone;

        /**
         * Triggered on the initial subscription.
         * @param subscription An instance of Flow.Subscription.
         */
        @Override
        public void onSubscribe(Flow.Subscription subscription) {
            System.out.println("Subscribed");
            this.subscription = subscription;
            this.subscription.request(1);
        }

        /**
         * Do the actual processing.
         * @param item The actual item currently being processed.
         */
        @Override
        public void onNext(Integer item) {
            System.out.println("Processing " + item);
            this.subscription.request(1);
        }

        /**
         * Holds how to handle error.
         * @param throwable An instance of Throwable.
         */
        @Override
        public void onError(Throwable throwable) {
            throwable.printStackTrace();
        }

        /**
         * Called with the publisher was closed or completed.
         */
        @Override
        public void onComplete() {
            System.out.println("Processing done.");
            isDone = true;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        
        //The publisher of the data.
        SubmissionPublisher<Integer> publisher = new SubmissionPublisher<>();

        //The sample subscriber implementation.
        Subscriber subscriber = new Subscriber();
        
        //Register a subscriber.
        publisher.subscribe(subscriber);

        //The sample stream to process.
        var intData = IntStream.rangeClosed(1, 10);

        //Publish the stream data. 
        intData.forEach(publisher::submit);

        //The publisher is done.
        publisher.close();

        //Since this is processing is asynchronous wait for everything to be processed. 
        while(!subscriber.isDone) {
            Thread.sleep(10);
        }
        
        System.out.println("Done");
    }
}

Resetting sa password in SQL Server Express

  1. Open the Services application and look for SQL Server (SQLEXPRESS).
  2. Stop the SQL Server (SQLExpress) service.
  3. Right-click the SQL Server (SQLExpress) service and select Properties.
  4. At the Start parameters field type in -m.
  5. Click the Start button.
  6. Close the Services application.
  7. Open a Command Prompt in elevated mode.
  8. Execute the following command:
    osql -S <LOCAL_PC_NAME>\SQLEXPRESS -E

    Note: The <LOCAL_PC_NAME> must be changed appropriately.

  9. At the prompt generated by the previous command invoke the following commands in sequence:
    sp_password NULL,'<NEW_PASSWORD>','sa'

    Note: Change <NEW_PASSWORD> to your desired password.

    go
    quit
  10. Close the  elevated Command Prompt.
  11. Repeat steps 1 to 6, but on step 4 remove -m  from the Start parameters field, if it exists.

Configuring Archiva with MariaDB in Synology Diskstation

  1. Install Tomcat 7 package in Diskstation
  2. Download archiva war file from the following address:
    https://archiva.apache.org/index.cgi
  3. Place the downloaded war file (e.g. apache-archiva-2.2.3.war) into the following directory:
    /volume1/@appstore/Tomcat7/src/webapps/
  4. In MariaDB, add the following user with appropriate password.
    archivauser

    and the following database

    archiva
  5. Download the following jar files:
    mail-1.4.jar 
    mariadb-java-client-1.5.x.jar
  6. Place the download jar files in the following directory:
    /volume1/@appstore/Tomcat7/src/lib
  7. Create archiva.xml file in the following location:
    /volume1/@appstore/Tomcat7/src/conf/Catalina/localhost

    Add the following entries:

    <?xml version="1.0" encoding="UTF-8"?>
    <Context path="/archiva" docBase="/volume1/@appstore/Tomcat7/src/webapps/<ARCHIVA_WAR_FILENAME>">
    <Resource name="jdbc/users" auth="Container" type="javax.sql.DataSource"
    	username="archivauser"
    	password="<PASSWORD_HERE>"
    	driverClassName="org.mariadb.jdbc.Driver"
    	url="jdbc:mariadb://<MARIADB_HOST_IP>:<MARIADB_HOST_PORT
    	/archiva?autoReconnect=true" />
    <Resource name="mail/Session" auth="Container" 	type="javax.mail.Session" mail.smtp.host="localhost"/>
    </Context>

    Note: The <ARCHIVA_WAR_FILENAME>, <PASSWORD_HERE> <MARIADB_HOST_IP> and <MARIADB_HOST_PORT tokens must be replaced by the downloaded war file from step 2, password used from step 4, IP address of MariaDB and port used by MariaDB repectively.

  8. Access archiva using the following address:
    http://<DISKSTATION_HOST_IP>:7070/archiva

    Note: Update the token <DISKSTATION_HOST_IP> with the IP of your Synology Diskstation.

Configuring Tomcat 7 Package in Synology Diskstation

  1. Install Tomcat 7 package.
  2. Edit the following file:
    /volume1/@appstore/Tomcat7/src/conf/tomcat-users.xml
  3. Add the following entries:
    <role rolename="manager-gui"/>
    <user username="admin" password="<PASSWORD_HERE>" roles="manager-gui"/>

    Note: Update the token <PASSWORD_HERE> appropriately.

  4. Access the manager-gui using the following address format:
    http://<DISKSTATION_HOST_IP>:7070/manager/html

    Note: Update the token <DISKSTATION_HOST_IP> with the IP of your Synology Diskstation.

Using JShell for testing an API

Java 9 was released and JShell (i.e. The REPL of Java) is now real and we can use this to test an API.

For example if we want to check the reverse function StringUtils from the commons-lang3-3.1.jar.
1.) Using windows terminal (i.e. cmd command).
2.) From this directory execute to following command jshell command.
jshell --class-path .\commons-lang3-3.1.jar
Expect to see something similar to the following:
Welcome to JShell -- Version 9.0.1
For an introduction type: /help intro

jshell>
3.) From the jshell prompt import the class org.apache.commons.lang3.StringUtils just like we normally do in java and then press enter.
e.g.
jshell> import org.apache.commons.lang3.StringUtils
4.) To optionally check all the imported classes on the current jshell session we can use /imports command.
e.g.
jshell> /imports
The sample output would be:
|    import java.io.*
|    import java.math.*
|    import java.net.*
|    import java.nio.file.*
|    import java.util.*
|    import java.util.concurrent.*
|    import java.util.function.*
|    import java.util.prefs.*
|    import java.util.regex.*
|    import java.util.stream.*
|    import org.apache.commons.lang3.StringUtils
5.) Since we know that the StringUtils class was already loaded. We can now execute its reverse function.
e.g.
jshell> StringUtils.reverse("abcde")
The output must be:
$2 ==> "edcba"
Note: if you want to exit jshell execute the /exit command.

Enable Windows Subsystem for Linux (WSL) and Install Linux Distribution

If you want to install any Linux distributions for WSL ensure that the Microsoft-Windows-Subsystem-Linux optional feature is enabled using the following procedure:

  1. Open a PowerShell as Administrator and run the following (i.e. if it is not installed):
    Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
  2. Restart the computer when prompted.
  3. Open the Microsoft Store
  4. Search for the Linux distribution (e.g. Ubuntu) you like.
  5. Click it and the click the Install button.
  6. After finishing the installation search for it in the Start menu.

    Usually the newly installed application is at the top of the start menu.

« Older posts Newer posts »