Copy all but some properties of an object in ES6

Since I started playing with ES6 about half a year ago I really came to love the new syntax, as it provides a much more python-ish feel to Javascript development.

One of the functions I like the most is the awesome Object.assign().

You can use it for all sorts of things:

const oldObject = { foo: 'bar', baz: 42 };
// (shallow) copy an object
const newObject = Object.assign({}, oldObject);
// overwrite some values
const overwritten = Object.assign({}, oldObject, { foo: 'fighters' });
// overwritten is { foo: 'fighters', baz: 42 }
// merge objects
const other = { luftballons: 99 };
const merged = Object.assign({}, oldObject, other);
// merged is { foo: 'bar', baz: 42, luftballons: 99 }

and more awesomeness that you can find, as always, on the MDN site.

One thing that I found out today that made my day better is that you can use Object.assign() to copy an object except for some of its properties.

const oldObject = { foo: 'bar', baz: 42 };
let noFoo = Object.assign({}, oldObject, { foo: undefined });
// noFoo is { foo: undefined, baz: 42 }
// this call is also equivalent to this
noFoo = { ...oldObject, foo: undefined };

[Edit – July 2019]: if you iterate through your items and check/filter for truthiness, this might be enough. However, if you can target ES2018, there’s a new syntax that actually removes the key as well:

const oldObject = { foo: 'bar', baz: 42 };
const { foo, ...noFoo } = oldObject
// now noFoo is { baz: 42 }

See this post about the rest/spread operator in ES2018

As easy as that!

I find myself doing this kind of operation quite often, namely when I decorate some object generated from JSON retrieved from a server and want to send it back after changing it client-side. This syntax makes it oh-so-simple!

IntelliJ Idea adds tags when typing ‘t

This was quite annoying, especially since I failed at googling a cure for it.

What happens: whenever you type “'t” in a comment on a Java file in Idea followed by a whitespace, it gets replaced with “<></>“, and whatever you type after that is added as if it were an HTML tag pair.

If you actually pause after typing “'t” (which I don’t know why it’s something I never did until now), you’ll notice IntelliJ’s auto-complete popup telling you what’s going on:

popup

It turns out that “t” is the shortcut for “tag pair”, which might be awesome for HTML coding, but it’s not as nice when you’re writing comments.

To disable that, go to Settings/Editor/Live Templates/, expand the html/xml line, and uncheck t (tag pair). Hit OK, and it’s gone!

After upgrading, Jenkins doesn’t start: org.xml.sax.saxparseexception: premature end of file

I recently upgraded my Jenkins installation using Debian’s package manager, and to my surprise… Jenkins wouldn’t start!

The error logged in /var/log/jenkins/jenkins.log looked like this:

WARNING: Failed startup of context w.{,file:/var/cache/jenkins/war/},/var/cache/jenkins/war
org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Premature end of file.

followed by a Java stack trace. I noticed a suspicious line in that stack trace:

at org.eclipse.jetty.webapp.MetaData.setWebXml(MetaData.java:170)

interesting. It looked like something was wrong with Jenkins’ web.xml, so I checked /var/cache/jenkins/war/WEB-INF/web.xml and, surprise surprise… it was empty!

I unpacked an old jenkins.war that I had, and copied its web.xml over, restarting the service. A-ha! The logged error changed. Unfortunately, it still wouldn’t start, but it made me look for “jenkins corrupted /var/cache” which finally lead me to this bug report.

“Dang!” – I thought – “is that it?”.

Moved the old /var/cache/jenkins away, created a new empty directory, and set user jenkins as its owner:

mv /var/cache/jenkins ~/var-cache-jenkins-back
mkdir /var/cache/jenkins
chown -R jenkins:jenkins /var/cache/jenkins
service jenkins start

sonofa… it worked!

Fix multiple launcher icon issue in Ubuntu unity

I’m so glad I found out how to fix this, because it’s an issue that just kept popping up every now and then.

The issue is this: for some applications, especially (but not necessarily) after upgrades, Unity somehow decides to spawn a new icon every time the app is launched. Thus, you end up with two identical (or in the case of upgrades, very similar) versions of the icon in the Unity launchbar, with the additional annoyance of having one work as a window switcher, and the other working as a new launcher.

Here’s how to fix that.

1. Locate your application’s .desktop file

In Ubuntu this is either inside ~/.local/share/applications or inside /usr/share/applications.

One problem you may have is that you have more than one .desktop file for the same application. If that is the case, remove one (probably the older one).

The .desktop files don’t necessarily match the application name that’s shown when you hover on the launcher (wonderful design idea, duh), so you might need to use grep to find the file.

For example, to find my PyCharm launcher, I had to execute

ls ~/.local/share/applications | grep -i charm

which returned jetbrains-pycharm.desktop, the file that I was looking for.

Removing duplicate .desktop files might be enough to solve the issue, so try launching your app to see if that fixed it. Otherwise, read on.

2. Find your application’s WM_CLASS

This was the core of the issue in my case. To match a window to an application, Unity looks for the window’s WM_CLASS.

To find what your application’s WM_CLASS is, launch your app and run this in a terminal (using a small window for the terminal, leaving your app visible in the background, you’ll see why in a moment):

xprop WM_CLASS

your mouse cursor will turn into a crosshair, and you must click anywhere on your application’s window. You will find something like this in your terminal:

WM_CLASS(STRING) = "sun-awt-X11-XFramePeer", "jetbrains-pycharm-ce"

(this is the output for PyCharm Community Edition). Your WM_CLASS is the most specific string in the list (use your intuition, in this case jetbrains-pycharm-ce is obviously about PyCharm, whereas the other seems to be related to all Java apps in general).

3. Set your application’s WM_CLASS in the .desktop file

Open your .desktop file from Step 1 with a text editor, and either add (if it’s not there already) this line to the bottom, or replace its previous value with the WM_CLASS string from Step 2:

StartupWMClass=jetbrains-pycharm-ce

replacing jetbrains-pycharm-ce with your WM_CLASS, of course.

4. Profit

That’s it! Close all your application windows, and relaunch your app. This time, after you launch the app, you should only have one icon 🙂

Fix out of sync subtitles with Angular

In what seems to be a never ending series of posts on how to fix out of sync subtitles… here’s how to do it using Angular! 🙂

First things first: here’s a link to the webpage that you can use to fix your out of sync subtitles. Just go there and follow the instructions, it’s really easy. Trust me, I’m the author 😛

A little background on why I made that page. About a year and a half ago I started toying around with AngularJS, because we decided to re-write the SketchTogether HTML client in it. Since I’m mostly taking care of the server side of the app, I spent a lot more time reading Angular code than writing it; even if I think I got the basic concepts relatively quickly, I wanted to have some first-hand experience with the library to really grasp what it means to develop an app with it, even if just a basic one.

Since back in those days I was fiddling with a toy python script to fix out of sync subtitles, I decided that it could have been fun to do the same thing in Angular. I wrote a rough implementation of the script’s functionality in about two weeks of my off time (about 10 very fragmented hours all in all, and I must say I was happy with it, considering how Angular is known for its steep learning curve), and left it there. Fast forward to 4 months ago, I decided to make it look a little prettier, and publish it on GitHub. And then, it took me 4 more months to find the time to write this blog post about it on a Sunday night 😛

My experience with Angular so far has been positive. For one thing, it’s not as hard to create a non-trivial webpage with it as most people want you to believe. Data binding can get you pretty far, and it’s relatively straightforward (one basic thing that left me wondering though is the from-dashed-to-camelCase directive name auto-conversion… that felt a bit like unneeded magic to me).

It does get a bit convoluted when your application grows and you want to add some piece of functionality that’s like 4 lines of code in jQuery, but which takes a new directive definition, changes to the HTML, and maybe a new scope, just to follow the Angular way. But then again, it could be my limited knowledge of the library (which I intend to keep expanding, because there’s so much to learn!).

As with most things Javascript, there tends to be an oversupply of sub-libraries to do pretty much anything. For subslider.js, for example, I found a lot of angular plugins to take care of pagination, with no clear winner. The same applies for drag-and-drop support (which in the end was implemented as a directive in the app). It really takes some time to simply understand which of the many plugins suits you best… just look at how many plugins are listed by ngmodules!

Oh, and one last thing. The “there should be a dot in your model” rule should be re-stated everywhere in the documentation. Once you really understand what it is about, you experience one of the major bumps in the famous “feelings about angular over time” graph from this post 🙂

A template to create log4j Logger objects in Eclipse

In my (server) Java apps, I usually use log4j to keep logs. These days, I actually use SLF4J as a proxy for log4j, mostly because the framework I’m using (Vert.x) uses it.

Over the years I’ve tuned my log format to only store the information I care about, and nothing more than that:

<PatternLayout pattern="[%d{HH:mm:ss.SSS}] %p %c{3} - %m%n" />

so I have a timestamp, the log level (%p), the class name with up to 3 levels of package hierarchy (%c{3}), and the new-line-terminated message (%m%n).

A sample line:

[11:39:36.667] TRACE redis.redis_client.RedisDecoder - received new MultiBulkReply

This format requires a Logger object in all classes that need logging, which requires quite a bit of boilerplate code, e.g.:

private static final Logger LOGGER = LoggerFactory
    .getLogger(SlackRouter.class);

You quickly grow tired of typing all of that. But worry not! Eclipse comes to the rescue!

Setup an Eclipse Template

I created a template that does the work for me: now, all I have to do to add a new Logger object is type log, hit Ctrl + space, and select “Insert logger”.

Just like this:

Adding a Logger

Note that typing “log4” instead of “log” only gives you one option, saving 2 precious key strokes! 😛

Here’s how to set it up for your Eclipse.

  1. Open your Eclipse Preferences menu
  2. Type “java editor templates” in the search bar
    uno
  3. Hit the “New” button
  4. Set “log4j” as name (or whatever you want the shortcut to be), add a description, paste this in the “Pattern” field:
    ${:import(org.slf4j.Logger,org.slf4j.LoggerFactory)}
    private static final Logger LOGGER = LoggerFactory.getLogger(${enclosing_type}.class);
    

    and hit “OK”
    tre

  5. That’s it!

    If you’re not using SLF4J, all you need to do is change the import code to include the actual class you use.

Find the most recent file/folder in a folder with Java 8

A simple snippet that shows how Java 8 lambdas can be really nice to replace operations that used to require a lot of boilerplate in earlier versions of Java.

If you want to find the most recent file or subfolder in a folder with Java 8, here’s what you need to do:

Path parentFolder = Paths.get("path", "to", "your", "file");

Optional<File> mostRecentFileOrFolder =
    Arrays
        .stream(parentFolder.toFile().listFiles())
        .max(
            (f1, f2) -> Long.compare(f1.lastModified(),
                f2.lastModified()));

if (mostRecentFolder.isPresent()) {
    File mostRecent = mostRecentFileOrFolder.get();
    System.out.println("most recent is " + mostRecent.getPath());
} else {
    System.out.println("folder is empty!");
}

The very nice thing is that you can take advantage of the flexibility of Java 8 streams to either make the operation parallel (just throw in a parallel() call after Arrays.stream()), or to filter results according to other criteria.

For example, if you’re only interested in one type of child elements (a file or a folder), you could…

// if you're only interested in files...
Optional<File> mostRecentFile =
    Arrays
        .stream(parentFolder.toFile().listFiles())
        .filter(f -> f.isFile())
        .max(
            (f1, f2) -> Long.compare(f1.lastModified(),
                f2.lastModified()));

// if you're interested in folders...
Optional<File> mostRecentFolder =
    Arrays
        .stream(parentFolder.toFile().listFiles())
        .filter(f -> f.isDirectory())
        .max(
            (f1, f2) -> Long.compare(f1.lastModified(),
                f2.lastModified()));

Getting the Git commit id of a Gerrit Change Set

Oddly enough, Gerrit doesn’t report the Git commit id of its Change Sets.

The only way I found to get that piece of information is to use its SSH interface, using the query command.

The syntax is this:

ssh -p 29418 user@gerritHost gerrit query --current-patch-set <ChangeId>

replacing 29418 with the port you normally use to contact Gerrit via SSH.

That will display a number of properties about the Change Set, including the revision parameter which is the extended version of the Git commit id.

You can use the --format JSON option if you want to get a JSON representation of the same data, or you can get the short commit id using for example:

ssh -p 29418 user@gerritHost gerrit query --current-patch-set <ChangeId> \
cut -d':' -f2 | cut -c2-7

List forwarding rules in VirtualBox running headless (even with older VBoxManage versions)

The VBoxManage command is very handy for managing virtual machines in servers running headless. Adding and removing forwarding rules is super simple, you just call for example

# adding "rule1" for "vm_1" mapping TCP host_port to guest_port
VBoxManage modifyvm vm_1 --natpf1 "rule1,tcp,,host_port,,guest_port"

# deleting that same rule
VBoxManage modifyvm vm_1 --natpf1 delete rule1

I created two simple scripts so that I don’t have to remember the exact syntax every time: vm_forward_add and vm_forward_delete. You run the commands with no arguments, and they tell you what you need to add.

Listing the existing rules is a bit more complex, as VBoxManage has no option for that (not the version that I use, at least).

This is where xmlstarlet comes to the rescue. Xmlstarlet is a command-line tool for parsing XML that comes pre-installed in most UNIX systems.

Since forwarding rules are stored in VirtualBox .vbox files, which are just big XML files storing all properties for a VM, we can grab the information we want from there.

This is the script that I use to list all forwarding rules. I can’t guarantee that it works with any version of VirtualBox, but it works with any version <=4.3 (the one I use).

Feel free to use the script, the worst that it can do is… not work 🙂

About things that weren't too obvious: you need to include the XML schema not only in the XPath of the XML node you're interested in, but in all definitions (!).

So, say you have a node with this path and these attributes (xmlstarlet el -a lists all XPaths available in the XML file):

me@server:~ xmlstarlet el -a my_vm.vbox | grep Forwarding
VirtualBox/Machine/Hardware/Network/Adapter/NAT/Forwarding
VirtualBox/Machine/Hardware/Network/Adapter/NAT/Forwarding/@name
VirtualBox/Machine/Hardware/Network/Adapter/NAT/Forwarding/@proto
VirtualBox/Machine/Hardware/Network/Adapter/NAT/Forwarding/@hostport
VirtualBox/Machine/Hardware/Network/Adapter/NAT/Forwarding/@guestport

To query those four attributes you need to specify the XML schema using the -N option (easy to find in xmlstarlet‘s docs), but you also need to set that schema for every single attribute name!

So, this will fail:

xmlstarlet sel -N x="http://www.innotek.de/VirtualBox-settings" -t \
-m "//x:Machine/Hardware/Network/Adapter/NAT/Forwarding" -v @name \
-o " " -v @hostport -o " " -v @guestport -n my_vm.vbox

but this will work (note the repeated x:):

xmlstarlet sel -N x="http://www.innotek.de/VirtualBox-settings" -t \
-m "//x:Machine/x:Hardware/x:Network/x:Adapter/x:NAT/x:Forwarding" \
-v "concat(@name, ' - host:', @hostport, ' guest:', @guestport)" \
-n my_vm.vbox

I wish this was more explicit in xmlstarlet documentation!