Aries' Blog

Freestyle technical blog

Java TimeZone DST practices

Timezone is a complex issue in Programmer’s world. Coupled with Java’s legacy datetime API it could be a nightmare. Below list some of the practices I followed when dealing with Timezone / DST (Daylight Saving Time).

1. Expect DST rules to change

DST rules changes upon each countries / cities political decision (sometimes for no reason). It changes very often and may have very short notice period.

2. Use TZDB ZoneId

A TZDB Timezone ID have format {area}/{city}, e.g. "Europe/Rome". TZDB ID is preferred over Three-Letter Timezone (e.g. CST), because it is less ambiguous and it takes DST into account.

Sample code for retrieving local Datetime with DST on Java 8

Instant instant = ts.toInstant();
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

3. Update tzdata regularly

ZonedDateTime calculate the DST depends on the tzdata stored in local JRE. Be sure to update tzdata regularly to incorporate incoming DST changes.

Artemis MQ with Springboot

ArtemisMQ is successor of ActiveMQ, using it with springboot is easy as auto-configuration is provided by spring-boot-starter-artemis. A starter project is created here. Below are some notes in using the starter project.

1. Artemis mode in Springboot config

There are 2 modes for the configuration spring.artemis.mode:

  • embedded
    Server mode, embed Artemis Server into the springboot app. Note: By default embedded server only accept internal connection. See point 2 to allow external connection.
  • native
    Client mode, no Artemis Server included. A JmsTemplate will be auto-configured for connecting to the Artemis Server specified by host & port properties.
    spring:
        artemis:
          mode: native  # client mode
          host: localhost
          port: 61616

2. Allow embedded Artemis server to receive external connection

By default embedded Artemis won’t accept external connection. To allow this, edit springboot default config with below code.

@Configuration
public class ArtemisConfig implements ArtemisConfigurationCustomizer {
    @Override
    public void customize(org.apache.activemq.artemis.core.config.Configuration configuration) {
        // Allow Artemis to accept tcp connections (Default port localhost:61616)
        configuration.addConnectorConfiguration("nettyConnector", new TransportConfiguration(NettyConnectorFactory.class.getName()));
        configuration.addAcceptorConfiguration(new TransportConfiguration(NettyAcceptorFactory.class.getName()));
    }
}

3. Artemis auto destination creation feature

There is no need to define destinations (e.g. queue) in Artemis Server as destination are auto created when first use (e.g. incoming message).

Regex notes

Regex is very useful but hard to remember, I use it infrequently and always forget the syntax.

Regex reserved characters

Chars Description
. Any single character.
( ) Grouping delimitators.
[ ] Character set delimiters. OR at character level
| OR expression for patterns (one or another).
{ } Repetitions delimiters.
* Zero or more repetitions of the previous character.
+ One or more repetitions.
? Zero or one repetition. Also it’s used for lazy matches.
^ Start of the string. You can use it to force a pattern to match only at the start. Also it’s used as a NOT inside of character sets.
$ End of the string.
/ Separator. In many regex engines, regex patterns must be enclosed in /s
- Range definition. Used to define a range of consecutive characters, like A-Z
\ Escape character for all reserved characters, so \? will search for a literal ?. It’s also used for other special search patterns (see below).

Below online regex tester can provide great help.

Unicode character

Use \x{FFFF} pattern to search for unicode. It works for both Java & Notepad++

1. Java

Java regex engine is similar to Perl one.

I found this Java Regex Tester most helpful as it provide as a Java string view of the Regex which you can use directly in code. This tester is based on Java 6.

Java Regex engine spec is documented in java.util.regex.Pattern API doc, this link to Java 8 one.

2. Notepad++

Notepad++ support regex search by selecting Regular expression under Search Mode in the search window. It supports PCRE (PERL Compatible Regular Expressions). Use this tester and select PCRE.

Note that / (forward slash) need to be escaped in tester but not in notepad++.

So patterns

^http(s?):\/\/my.com\/path\/to\/page and

^http(s?)://my.com/path/to/page

both work in notepad++, but only the first one is valid in the tester.

3. Grep

Use grep -E or simply egrep to activate Extended Regular Expressions function, then grep will behave like Notepad++.

Patterns

^http(s?):\/\/my.com\/path\/to\/page and

^http(s?)://my.com/path/to/page

both work with grep -E or egrep .

SpringBoot app start / stop script

Start / Stop script for springboot app on linux, with following features:

  1. Start script won’t create new instance if the app already running
  2. Run the app in background and forward all console output to “log.log”

1. Start Script

#!/bin/bash

if [ -f "./PID" ]; then
  echo "PID exists, app already running"
else 
  nohup java -jar ./MyApp-0.1-SNAPSHOT.jar > log.log 2>&1 &
  echo $! > PID
fi
 

2. Stop Script

#!/bin/bash

kill `cat ./PID`
rm PID

Trace dependency origin in maven pom

In large maven project sometime it’s hard to trace the origin of a dependency’s version (Especially with multi-level parent pom / spring-boot parent). In this case below command can help.

1. For maven version 3.2.0+

Use help:effective-pom with -Dverbose=true flag

mvn help:effective-pom -Dverbose=true

Sample output

<project>
...
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>  <!-- org.springframework.boot:spring-boot-dependencies:2.0.5.RELEASE, line 208 -->
        <artifactId>spring-boot</artifactId>  <!-- org.springframework.boot:spring-boot-dependencies:2.0.5.RELEASE, line 209 -->
        <version>2.0.5.RELEASE</version>  <!-- org.springframework.boot:spring-boot-dependencies:2.0.5.RELEASE, line 210 -->
      </dependency>
      ...
    </dependencies>
  </dependencyManagement>
</project>