Logging Mockito invocations in Spring

@ExtendWith(SpringExtension::class)
abstract class AbstractSpringUnitTest {

    private val logger = LoggerFactory.getLogger(AbstractSpringUnitTest::class.java)

    @Autowired
    protected lateinit var ctx: ApplicationContext

    @AfterEach
    fun logMockingDetails() {
        ctx.beanDefinitionNames.forEach {
            val bean = ctx.getBean(it)
            if (MockUtil.isMock(bean)) {
                Mockito.mockingDetails(bean)
                    .invocations.forEach { invocation -> logger.info("Mock invocation: $invocation") }
            }
        }
    }
}

Kotlin – type checking Hibernate entities

When using Kotlin and JPA + Hibernate and especially JPA inheritance, you will probably want to type check a polymorphic entity:

val request: RequestEntity = requestRepository.findById(123)
val response: ResponseEntity? = request.response // response is LAZY mapped
return when (response) {
    null -> "pending"
    is ResponseErrorEntity -> "error"
    is ResponseRejectedEntity -> "rejected"
    is ResponseAcceptedEntity -> "accepted"
}

You might be surprised to get following exception:

kotlin.NoWhenBranchMatchedException: null

After all, compiler told us, that this when check is exhaustive.

The reason is, that the real type of response value is something like ResponseAcceptedEntity$HibernateProxy$WS7APdlA

if (response != null) {
    println(response::class)
    println(response is ResponseAcceptedEntity)
}

// package.ResponseAcceptedEntity$HibernateProxy$WS7APdlA
// false

To fix this without changing the mapping from LAZY to EAGER, we use a handy utility function, implemented as a Kotlin extension:

@Suppress("UNCHECKED_CAST")
fun <T> T.unproxy(): T = Hibernate.unproxy(this) as T

We use it explicitly on all lazily mapped entities, than need to be checked by their type:

val response: ResponseEntity? = request.response.unproxy()

Release multi-module Gradle project with Git tags

./gradlew createRelease --no-daemon -x verifyRelease -x test -x ktlint
./gradlew verifyRelease --no-daemon -x test -x ktlint --stacktrace
./gradlew pushRelease --no-daemon -x test -x ktlint --stacktrace
./gradlew artifactoryPublish  --no-daemon -x test --stacktrace

Connect to AWS RDS from your PC

Go to “Configuration”:

Click on the “Endpoint”:

Click on the DB name:

Click on any group:

Select “Inbound” and click “Edit”:

“Add rule”, choose type “MYSQL/Aurora”, Source “MyIP” and “Save”:

Test your connection:

Publishing libraries to local repository using SBT

In my project, I wanted to use ScalaJS wrapper for Google Maps from https://github.com/coreyauger/scalajs-google-maps. It turned out, that library artifacts are not published, where they were supposed to be.

Fortunately, it is very easy to build those artifacts yourself and use them in your project:

  1. Clone the project
  2. Deploy the project to your local repository
  3. Add dependency in your project

Run following commands:

git clone https://github.com/coreyauger/scalajs-google-maps.git
cd scalajs-google-maps
sbt publish local

Add dependency to your ScalaJS project:

libraryDependencies += “io.surfkit” %%% “scalajs-google-maps” % “0.0.3”

Multiple OpenVPN connections on Windows 7

It is possible to connect to multiple networks using OpenVPN for Windows. Here are the steps, that enabled me to connect to 3 VPNs at once on my Windows 7 machine.

This guide was compiled from two StackOverflow answers:

There are limitations to this. Quoting answer by zoredache from the first link:

Obviously you will also need to make sure that nothing about your various VPNs conflict with each other. For example if one is modifying the default gateway you are probably going to have problems. If nothing is changing the default gateway and there are no overlapping IP addresses then you may be ok.

The key is to create multiple TAP adapters, one per every VPN connection.
After you install OpenVPN, you will have one TAP adapter automatically created (I already renamed it, but it was named “Local Area Connection 2” before):

Later, I created two more TAP adapters. After you install OpenVPN, you will also have utilities installed under Start/All Programs/TAP-Windows. Or you can search for it directly using “Add a new TAP”. The script needs to be executed with administrator privileges. Right click on the shortcut (try shift+right click, if it does not work) and “Run as administrator”:

Search for “View network connections”. You will see that a new adapter has been created. You should rename it and give it a simple descriptive name.


I created two additional TAP adapters and named all of them TAPVPN1, TAPVPN2 and TAPVPN3:

The last step is to update your *.ovpn configuration files. For every VPN, add a new setting “dev-node %ADAPTER_NAME%”, e.g.:

...
ns-cert-type server
comp-lzo
verb 3‏
dev-node TAPVPN3
...

Final result:

 

Logging multiline strings

Simple answer – don’t log multiline string. You will loose or benefits coming from tools like grep. The philosophy of these tools is, that every line is a self-contained piece of information. Spreading the information across multiple lines breaks the concept.

So what to do with ‘\n’ or ‘\r’ characters? Replace (escape) them with them literally with “\n” or “\r”. Apply the same to ‘\t’ (tab) and ‘”‘ (double quotes) as well. For example a message like

Response: {
   code: 1,
   message: "No errors found"
}

would by written to a log message like this:

[2015-01-03 16:26:23.136049] ERROR: Response: {\n    code: 1,\n    message: \"No errors found\"\n}

An example of a logging library that enables this behavior is https://github.com/Seldaek/monolog for PHP.

Now it is possible to grep such logs, but they don’t look pretty and are hard to read visually. Here is how to escape back previously escaped characters while tailing multiple logs.

tail -f /var/log/httpd/error_log /var/log/httpd/vhost15/error_log | grep -v " \[info\] " | sed 's/\\r\\n/\n/g; s/\\r/\n/g; s/\\n/\n/g; s/\\t/\t/g; s/\\"/"/g;'

We are using Linux command sed, which is basically a command line text editor. Traditional text editors are interactive, they come with a GUI, where text is displayed, user moves a cursor around and types down the text. Some editors allow to record macros. Macros are small programs and allow to repeat repetitive tasks. sed is a text editor with macros, but without GUI. Because it is a command line utility, it can be combined with other command line utilities, e.g. with tail

In this case, we use sed to recognize simple regular expressions and replace them with other characters. More concretely, we replace escaped Windows EOL (\r\n) with a simple UNIX EOL, escaped Mac EOL with UNIX EOL, escaped UNIX EOL with UNIX EOL itself too and escaped TAB with TAB itself.

Playing Master of Orion 2 in a DOSBox

Master of Orion 2 is a superb strategy game. It was released in year 1996. It is year 2015 now and I still conquer the galaxy now and then, when I really have nothing better to do.

Let’s assume, that c:\Games\ORION2CD is the directory with the installation files. Start the DOSBox, mount the directory with games, install the game to c:\ORION2 and setup soundcards (first listed soundcards worked for me):

mount c: c:/games
c:
cd ORION2CD
INSTALL.EXE

You can upgrade the game to any released patch by replacing files in c:\ORION2 with patched files. Patch 1.31 is recommended because it brings various improvements to the UI (e.g. ship refit screen).

Let’s create a convenient shortcut which launches the game. Here is the final setup:

 Directory of c:\Games

01/04/2015  10:15 PM    <DIR>          .
01/04/2015  10:15 PM    <DIR>          ..
01/04/2015  10:16 PM    <DIR>          ORION2
01/04/2015  10:23 PM               108 orion2.conf
01/04/2015  10:16 PM             1,978 orion2.lnk
01/04/2015  10:14 PM    <DIR>          ORION2CD
               2 File(s)          2,086 bytes

These are the contents of orion2.conf:

[sdl]
windowresolution=1300x975
output=overlay

[autoexec]
mount c: c:/games
c:
cd orion2
orion2.exe

And here is the target of orion2.lnk:

"C:\Program Files (x86)\DOSBox-0.74\DOSBox.exe" -conf "c:\games\orion2.conf" -noconsole -exit

Careful though! The game causes severe addiction ! 🙂