December 28, 2012

PostgreSQL JDBC pool exhaustion under Play Framework 2.1-RC1

After experimenting with Scala and Play Framework version 2.1-RC1 and the default H2 Database, I decided to switch over to use PostgreSQL for persistence.

After installing PostgreSQL 9.2.2 and creating my test user and database, I reconfigured my Play application.

Update project/Build.scala to include the PostgreSQL driver as a dependency. val appDependencies = Seq( jdbc, anorm, "postgresql" % "postgresql" % "9.1-901-1.jdbc4" )

Update conf/application.conf to use the PostgreSQL driver for the database named "default". db.default.driver=org.postgresql.Driver db.default.url="postgres://testuser:testpass@localhost:5432/testdb" #db.default.user=sa #db.default.password=""

When applying database evolutions, the database connection pool would be exhausted:
org.postgresql.util.PSQLException: FATAL: remaining connection slots are reserved for non-replication superuser connections


The only solution was to restart the Play application entirely as I wasn't inclined to increase the connection limit without knowing why the existing limit was being hit. Re-applying the evolution would trigger the problem again.

Per Play's JDBC settings documentation, I could adjust connection pools, but as far as I could tell, the pool size wasn't the actual issue, since PostgreSQL was configured to support more connections than Play should have been using.

In my case, the problem was due to how Play handles semicolons included in a quoted string within a DML statement (initially, I had attributed this to how JDBC itself handled semicolons). You can view the current approach to statement splitting in framework/src/play-jdbc/src/main/scala/play/api/db/evolutions/Evolutions.scala line 233. Questions about this approach can be viewed on Play's Google Group and on Play 2.0 pull request #134.

This issue causes the query to fail execution and the Evolutions code retries enough times to consume the server's available connections. As I'm inserting seed data, I removed the semicolon from the quoted string and corrected the values after the evolution was applied.

June 10, 2012

Missing class file for java.lang.Object in Eclipse

Having stumbled over this multiple times, usually after surgery on an Eclipse .project file or project properties, it's worth documenting the fix for posterity.

After some surgery on my Eclipse .project and .classpath files, I ran into the following errors in the Problems view:


The project was not built since its build path is incomplete. Cannot find the class file for java.lang.Object. Fix the build path then try building this project


…and…


The type java.lang.Object cannot be resolved. It is indirectly referenced from required .class files


In my case, these errors were shown only for the "last" Java class within a project. The class declaration line of the affected class had the following error tip:


Implicit super constructor Object() is undefined for default constructor. Must define an explicit constructor


This issue is caused by a missing JRE (or JDK) from the classpath, which can be added back in a few simple steps:

  1. Open the affected class file

  2. Under the Project menu, select Properties)

  3. Select Java Build Path in the left pane

  4. Select the Libraries tab in the right pane

  5. Click the Add Library... button

  6. Select JRE System Library from the list

  7. Click the Next > button

  8. Select the appropriate JRE (usually the Workspace default JRE option is fine)

  9. Click the Finish button

  10. Click the OK button to close the project properties.

April 13, 2012

Re-creating a Git branch while maintaining history and fast-forwardability

I am working on a project which used named branches in Git to represent long-lived stable and new feature code lines. When the new feature code line matures, its content becomes the new stable code line.

With Subversion, this can by done by deleting the stable code line and re-creating it from the new feature one via svn copy. Developers update their checkout of the stable code line to get the latest source tree. The stable code line's history will show the deletion and subsequent copy from the new feature code line.

Re-branching from new feature With Git, one way to do this is to create a new stable code line by branching the new feature code line. History for the old stable code line effectively disappears as there is no way to reach the old stable commits from the new branch HEAD. The history will also not show that the stable code line was recreated as it will simply inherit all history from new feature (stable becomes a named reference to the same commit as newfeature). A reset HEAD~ on the new stable branch would move you back to prior newfeature commits rather than prior stable ones (the latter being the likely intent). If you take this approach, you may want to tag the "last" stable commit before the branch was re-created. Also note that using this model, you typically have to use the --force option when pushing this change, since the latest stable commit will not be a child of the remote HEAD. Additionally, this would have caused the stable code line history to "originate" from newfeature, which is not what I wanted.

This approach also forces developers to perform some sort of client-side reset since there is no relationship between the old stable code line and the new. Additionally, a developer who (perhaps unintentionally) tries to merge the new stable code line onto their old (local) copy may run into conflicts and will reintroduce commit history which was intended to exist only in the old code line. Developers could re-create their local stable branches by deleting and re-branching from origin/stable, or by using the reset command. For developers who are new to Git, this may be daunting and require assistance from a local Git expert.

To make this easier on developers and make the history reflect the branch refresh, my intention was to create a commit which made the contents of the stable code line match newfeature while allowing a developer to apply this change as a fast-forward.

I started with a stable branch and a newfeature branch with the following HEAD commits.
$ git show --format=raw stable
commit 257a33187c5609de59578d0dfdb4633e83f3a6f5
tree db2dbcf8136a2ebb1eb7601ac8857850bb4d803f
parent 3a4e4655e3d064227b7b0a071707bcbbda756bbb
author Example User <user@example.com> 1334380489 -0700
committer Example User <user@example.com> 1334380489 -0700

Minor change

diff --git a/bar b/bar
index 257cc56..cbdbed2 100644
--- a/bar
+++ b/bar
@@ -1 +1,2 @@
foo
+foo too
$ git show --format=raw newfeature
commit f437becce4d71caae02c71a148c9fe3c1aa79a33
tree 91eeb5e6d9e74d71adadad473771e050b8786ab3
parent 6950c0de35c85ea33f666a45f8df9856c2cc2b67
author Example User <user@example.com> 1334380773 -0700
committer Example User <user@example.com> 1334380773 -0700

Add empty foo

diff --git a/foo b/foo
new file mode 100644
index 0000000..e69de29



Initially, I tried using the "ours" merge strategy. To make stable (theirs) look like newfeature (ours), I would have to merge stable into newfeature. However, I didn't want newfeature's history to advance, since it was only the stable branch that should change during this refresh (the graph for the new commit should be directed away from newfeature).

Merge with newfeature as first parent Creating a branch from newfeature initially seemed to work, but because stable was the "other" branch, it becomes the second parent commit whereas I wanted it to be the first. In this case, a reset HEAD~ leaves the working copy on a newfeature commit.
$ git checkout -b stable_temp newfeature
Switched to a new branch 'stable_temp'
$ git merge -s ours stable
Merge made by the 'ours' strategy.
$ git checkout stable
Switched to branch 'stable'
$ git merge stable_temp
Updating 257a331..b2be7ad
Fast-forward
bar | 3 +--
baz | 1 +
too/foo | 2 ++
3 files changed, 4 insertions(+), 2 deletions(-)
create mode 100644 baz
create mode 100644 foo
create mode 100644 too/foo
$ git branch -d stable_temp
Deleted branch stable_temp (was b2be7ad).
$ git show --format=raw stable
commit b2be7ad272cc767461310f897dbf6430ad95c402
tree 91eeb5e6d9e74d71adadad473771e050b8786ab3
parent f437becce4d71caae02c71a148c9fe3c1aa79a33
parent 257a33187c5609de59578d0dfdb4633e83f3a6f5
author Example User <user@example.com> 1334380832 -0700
committer Example User <user@example.com> 1334380832 -0700

Merge branch 'stable' into stable_temp



If you try this the other way around (merging newfeature into stable using the "ours" merge strategy), you end up with the parent commits ordered correctly but using the tree from stable).

Merge with stable as first parent The solution is to create a merge commit with its first parent as the latest stable commit and its second parent and tree identifier from the most recent newfeature commit. I couldn't find a way to do this with the merge command, so I created a synthetic commit using some lower-level Git tools. A reset HEAD~ leaves the working copy on the previous stable commit.
$ git show --format=raw newfeature | grep ^tree
tree 91eeb5e6d9e74d71adadad473771e050b8786ab3
$ git checkout stable
Switched to branch 'stable'
$ echo "Refreshed 'stable' branch to match 'newfeature' tree" | \
git commit-tree 91eeb5e -p stable -p newfeature | \
xargs git merge

Updating 257a331..7269777
Fast-forward
bar | 3 +--
baz | 1 +
too/foo | 2 ++
3 files changed, 4 insertions(+), 2 deletions(-)
create mode 100644 baz
create mode 100644 foo
create mode 100644 too/foo
$ git show --format=raw stable
commit 7269777c640403b00dd2a60bf69a738e6f052a21
tree 91eeb5e6d9e74d71adadad473771e050b8786ab3
parent 257a33187c5609de59578d0dfdb4633e83f3a6f5
parent f437becce4d71caae02c71a148c9fe3c1aa79a33
author Example User <user@example.com> 1334381250 -0700
committer Example User <user@example.com> 1334381250 -0700

Refreshed 'stable' branch to match 'newfeature' tree



With the second (correct) approach, the stable branch is the first parent and the tree is from newfeature.

You can then push the updated stable branch to any relevant remotes.

March 24, 2012

Bonjour-based multicast DNS on Windows 2000

Multicast DNS is convenient for local hostname resolution within a home network. On Windows, Apple's Bonjour library provides an implementation, but the latest version (2.0.2) requires Windows XP SP2 or higher. Bonjour 1.0.6 works on Windows 2000 but requires some additional steps before installation will complete successfully.

After initial installation is complete, install Windows 2000 SP4 (W2KSP4_EN.EXE).

Install update rollup 1 for Windows 2000 SP4 (Windows2000-KB891861-v2-x86-ENU.exe, see knowledge base article #891861). If this update is not installed, Bonjour installation will fail with an "Entry Point Not Found" error when running mDNSResponsder.exe:

The procedure entry point HeapSetInformation could not be located in the dynamic link library KERNEL32.dll


If this error occurs, click OK and then click Cancel to stop the Bonjour installer, since the error will keep occurring and installation will never complete.

Install Windows installer 3.1 (WindowsInstaller-KB893803-v2-x86.exe, see knowledge base article #893803).

Install Bonjour 1.0.6 (BonjourSetup.exe, also known as version 1.0.106).

When the Bonjour installer tries to install Apple Software Update, the following error will occur:

Module C:\Program Files\Apple Software Update\ScriptingObjectModel.dll failed to register. HRESULT -2147024769. COntact your support personnel.


The warning dialog gives the options of Abort, Retry, and Ignore. If you select Abort, Apple Software Update will be uninstalled, but Bonjour installation will continue normally. Ignore will continue with the Apple Software Update installation with no apparent ill effects (although I am not planning to use it to keep my Apple software up to date). See this thread on Apple's support community which suggests that Apple Software Update isn't supported on Windows 2000 (suggesting Abort is the best response to the warning dialog).

Once installation was complete, I was able to resolve local hostnames with multicast DNS.

C:\>ping -n 1 otherhost.local Pinging otherhost.local [192.168.1.2] with 32 bytes of data: Reply from 192.168.1.2: bytes=32 time<1ms TTL=128 Ping statistics for 192.168.1.2: Packets: Sent = 1, Received = 1, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 0ms, Maximum = 0ms, Average = 0ms

March 11, 2012

Opaque Blogger error codes

While there is a full site dedicated to translating Blogger error codes, there was no entry for error code bX-5wpe8v.

Only one question on the Blogger help forums mentioned this error and it remains unanswered.

This error occurred each time I tried applying a new custom (HTML) template to this blog using the new Blogger interface. After much experimentation (and lack of success), I was able to work around this issue by reverting back to the old Blogger interface and then editing the raw template.

March 10, 2012

Amending a non-HEAD commit in Git without changing commit dates

Given this history of commits to my master branch.

refs/heads/master:   A → B → C

$ git log --patch master
commit fa4e0e063a8d062038463264386eb5604ce2abfe
Author: Example User
Date: Sat Mar 10 07:47:51 2012 -0800

Third commit (C)

diff --git a/foo b/foo
index 5716ca5..8e60d72 100644
--- a/foo
+++ b/foo
@@ -1 +1 @@
-bar
+barter

commit 5aa9ba4c12d3b9ab7e878ef477f850c8b13550f7
Author: Example User
Date: Sat Mar 10 07:47:14 2012 -0800

Second commit (B)

diff --git a/bar b/bar
new file mode 100644
index 0000000..7601807
--- /dev/null
+++ b/bar
@@ -0,0 +1 @@
+baz

commit 1dc62c387c39caeb25440326729659f9ff2c9d6d
Author: Example User
Date: Sat Mar 10 07:46:25 2012 -0800

First commit (A)

diff --git a/foo b/foo
new file mode 100644
index 0000000..5716ca5
--- /dev/null
+++ b/foo
@@ -0,0 +1 @@
+bar


I had created commit C and then realized I had a typo in commit B that I wanted to fix. The commit --amend option doesn't allow editing a non-HEAD commit, and rebase --interactive alters commit dates.

Create a new temporary branch from commit B.

$ git branch temp 5aa9ba4

Checkout the new temp branch.

$ git checkout temp
Switched to branch 'temp'


Fix the relevant file(s) and add them to the index.

$ git add bar

Amend the commit.

$ git commit --amend
[temp 4168d24] Second commit (B)
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 bar


The history now looks like:

refs/heads/master:   A → B → C
refs/heads/temp:   A → B′

Switch back to the master branch.

$ git checkout master
Switched to branch 'master'


Remove the problematic commit (B) from the history (h/t StackOverflow).

$ git rebase --committer-date-is-author-date \
--onto 5aa9ba4^ 5aa9ba4 HEAD

Current branch HEAD is up to date, rebase forced.
First, rewinding head to replay your work on top of it...
Applying: Third commit (C)


The history now looks like:

refs/heads/master:   A → C′
refs/heads/temp:   A → B′

Re-play master's commits (in this case C′) against temp branch with the revised commit.

$ git rebase --committer-date-is-author-date temp

The history now looks like:

refs/heads/master:   A → B′ → C″
refs/heads/temp:   A → B′

Remove the temp branch as its history has been included in the revised master branch.

$ git branch --delete temp

The branch history has been altered after commit A.
$ git log --patch master
commit 61789d3254aae0a77389480724304b1f8de774a1
Author: Example User
Date: Sat Mar 10 07:47:51 2012 -0800

Third commit (C)

diff --git a/foo b/foo
index 5716ca5..8e60d72 100644
--- a/foo
+++ b/foo
@@ -1 +1 @@
-bar
+barter

commit 4168d24fa8b382062b24013bdcc5d2b923f3d816
Author: Example User
Date: Sat Mar 10 07:47:14 2012 -0800

Second commit (B)

diff --git a/bar b/bar
new file mode 100644
index 0000000..d9ce209
--- /dev/null
+++ b/bar
@@ -0,0 +1 @@
+bazaar

commit 1dc62c387c39caeb25440326729659f9ff2c9d6d
Author: Example User
Date: Sat Mar 10 07:46:25 2012 -0800

First commit (A)

diff --git a/foo b/foo
new file mode 100644
index 0000000..5716ca5
--- /dev/null
+++ b/foo
@@ -0,0 +1 @@
+bar


The commit SHA1s will change, so don't do this if you've already pushed your commits to a remote repository.