Fix “Communications link failure” in Java applications with MySQL

You may have problems connecting to MySQL from Java applications using Connector/J (the Java connector for MySQL) after upgrading/migrating MacPorts to a newer version. It happened to me after updating Mac OS X to El Capitan and upgrading MacPorts to work with it. Everything worked fine with phpMyAdmin and other applications using PHP but Java applications wouldn’t connect:

Exception in thread "main" java.lang.IllegalStateException: Cannot connect the database!
	at Main.main(Main.java:19)
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
	at com.mysql.jdbc.Util.handleNewInstance(Util.java:404)
	at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:983)
	at com.mysql.jdbc.MysqlIO.(MysqlIO.java:339)
	at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2252)
	at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2285)
	at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2084)
	at com.mysql.jdbc.ConnectionImpl.(ConnectionImpl.java:795)
	at com.mysql.jdbc.JDBC4Connection.(JDBC4Connection.java:44)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
	at com.mysql.jdbc.Util.handleNewInstance(Util.java:404)
	at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:400)
	at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:327)
	at java.sql.DriverManager.getConnection(DriverManager.java:664)
	at java.sql.DriverManager.getConnection(DriverManager.java:247)
	at Main.main(Main.java:16)
Caused by: java.net.ConnectException: Connection refused
	at java.net.PlainSocketImpl.socketConnect(Native Method)
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:345)
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
	at java.net.Socket.connect(Socket.java:589)
	at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:214)
	at com.mysql.jdbc.MysqlIO.(MysqlIO.java:298)
	... 15 more

You can test a simple connection in Java with this code in a file named Main.java:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class Main {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/database_name";
        String username = "username";
        String password = "password";

        System.out.println("Connecting database...");

        try (Connection connection = DriverManager.getConnection(url, username, password)) {
            System.out.println("Database connected!");
        } catch (SQLException e) {
            throw new IllegalStateException("Cannot connect the database!", e);
       }
    }
}

And running it like this (you’ll have to download the Java MySQL connector and place it in the same path with the .java file):

$ javac Main.java
$ java -cp .:./mysql-connector-java-5.1.37-bin.jar Main

I could connect to MySQL databases from the console using mysql so my server was running. I checked the usual configurations in my.cnf and didn’t see nothing wrong. The binding address was correct (it was 0.0.0.0 so connections from any IP could be done) and the socket file was also fine.

# Use default MacPorts settings
!include /opt/local/etc/mysql55/macports-default.cnf

[client]
port            = 3306
socket          = /opt/local/var/run/mysql55/mysqld.sock

[mysqld]
port            = 3306
socket          = /opt/local/var/run/mysql55/mysqld.sock
bind-address    = 0.0.0.0
max_allowed_packet = 256M

And then I saw it. Look at the include line. The problem was that the /opt/local/etc/mysql55/macports-default.cnf file in that include had been rewritten when MacPorts was updated and it had the skip-networking option enabled.

skip-networking

So the problem was solved by just commenting it out and restarting MySQL server.

Translate Symfony TimezoneType Field Type

The TimezoneType Field Type

Symfony has an specific Field Type to create a Timezone select widget in forms called TimezoneType. Very handy because it’s a pretty usual need in web applications.

select

It uses \DateTimeZone::listIdentifiers() to create the texts and as you can see those texts are in english:

    public static function getTimezones()
    {
        if (null === static::$timezones) {
            static::$timezones = array();

            foreach (\DateTimeZone::listIdentifiers() as $timezone) {
                $parts = explode('/', $timezone);

                if (count($parts) > 2) {
                    $region = $parts[0];
                    $name = $parts[1].' - '.$parts[2];
                } elseif (count($parts) > 1) {
                    $region = $parts[0];
                    $name = $parts[1];
                } else {
                    $region = 'Other';
                    $name = $parts[0];
                }

                static::$timezones[$region][$timezone] = str_replace('_', ' ', $name);
            }
        }

        return static::$timezones;
    }

¿But what if you want to translate all those texts to your language?

Note: I’m going to assume that you are storing the users timezone in the database as it’s defined in PHP. For example “Europe/Madrid” for Spain (without the Canary Islands) or “America/North_Dakota/New_Salem” for the Morton County in USA. This is the timezone we are going to use as an example.

As you can see the timezones are divided in different parts using the “/” character. The first one designates an area (more or less a continent but not exactly) and then a city. In some cases it has 3 parts for a more specific area. We also have some special ones like UTC for the Universal Time Clock.

We are going to start by creating our form with the TimezoneType for the user profile edit page:

<?php

namespace AppBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Validator\Constraints\UserPassword;

class ProfileFormType extends AbstractType
{
    private $class;

    public function __construct($class)
    {
        $this->class = $class;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $constraint = new UserPassword();

        $this->buildUserForm($builder, $options);

        $builder
            ->add('timezone', 'timezone', array(
                'label' => 'form.timezone',
                'translation_domain' => 'AppBundle',
                'choice_translation_domain' => true,
            ))
            ->add('current_password', 'password', array(
                'label' => 'form.current_password',
                'translation_domain' => 'FOSUserBundle',
                'mapped' => false,
                'constraints' => $constraint,
            ))
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => $this->class,
            'intention'  => 'profile',
        ));
    }

    public function getName()
    {
        return 'app_user_profile_form_type';
    }

    protected function buildUserForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('email', 'email', array(
                'label' => 'form.email',
                'translation_domain' => 'FOSUserBundle',
            ))
        ;
    }
}

It’s VERY important to use the translation_domain and choice_translation_domain options as seen above or this won’t work.

Then we have to create the translation files. Assuming you are following the Symfony Best Practices you have one bundle called AppBundle and its translation files, in YAML format, are in app/Resources/translations. The file name uses the locale code to designate the language, for example for spanish it would be AppBundle.es.yml. You can download a list of all the texts for english and spanish in those AppBundle.en.yml and AppBundle.es.yml files so you can use it as a template. This are some of those texts translated to spanish with our example in bold:

## app/Resources/translations/AppBundle.es.yml
# Timezone areas
Africa: "África"
America: "América"
Antarctica: "Antártida"
Arctic: "Ártico"
Asia: "Asia"
Atlantic: "Atlántico"
Australia: "Australia"
Europe: "Europa"
Indian: "India"
Pacific: "Pacífico"
# Specific timezones
Abidjan: "Abidjan"
Accra: "Accra"
Addis Ababa: "Addis Ababa"
Algiers: "Algiers"
# ... more and more timezones here ...
North Dakota - New Salem: "Dakota del Norte - New Salem"
# ... more and more timezones here ...
UTC: "UTC"

All we have to do now to see our TimezoneType Field Type translated to spanish is clear the cache ($ php app/console cache:clear --env=dev) and open our form page using the spanish locale. To force our application the spanish locale, if you aren’t already using multilanguage in your app, you can edit app/config/config.yml:

framework:
    translator:      { fallbacks: ["es"] }
    default_locale:  "es"

This is how my translated widget looks like:

translate_timezonetype

But we also want to translate the timezone stored in the database when showing it in the users profile page. Remember that we store the users timezone in its original PHP timezone string: “America/North_Dakota/New_Salem“. If we want to reuse all the translations we did before we can use this approach in Twig:

{{ (user.timezone|split("/")|first)|trans({}, 'AppBundle') }}

{{ (user.timezone|split("/", 2)|last|replace({'_': ' '})|replace({'/': ' - '}))|trans({}, 'AppBundle') }}

The first line will translate the timezone area (Africa, America, etc.) by spliting the timezone using the “/” character and then getting the first element. Becareful and remember using the opening and closing parenthesis before “|trans()” or this won’t work.

The second line is a little bit tricky. It splits the timezone string using the “/” character but limits the amount of parts to 2 and then gets the last item so we can discard the timezone area. If we take as an example “America/North_Dakota/New_Salem” we’ll have “North_Dakota/New_Salem” in this first step. Now we replace “_” with spaces and “/” with “ - “. This will convert “North_Dakota/New_Salem” to “North Dakota - New Salem” and if you look up there in the translation written in bold that’s exactly the key for the translation.

translated_timezone_text

¡HEY! ¡Don’t forget to clear your cache everytime you change or add a translation! They are not created on every request.

$ php app/console cache:clear --env=dev

Fix “This field was locked by vendor” in Plesk Updates source and installation settings

I was trying to install some new components to one on my Plesk managed servers but I got this error when going to “Server > Tools & Settings > Plesk > Updates and Upgrades”:

Failed to read product information from the file : Can't process products.inf3: Failed to download the package http://20141204-09h35m01s.parallels.mirrors.ovh.net.snapmirror.vps.ovh.net/parallels/products.inf3: The requested URL returned error: 404 Can't process versions.inf3: Failed to download the package http://20141204-09h35m01s.parallels.mirrors.ovh.net.snapmirror.vps.ovh.net/parallels/versions.inf3: The requested URL returned error: 404

I asked OVH technical service and they told me more or less this: “Yep, that URL is no longer available but we only provide it on first automated install. Fix it yourself.”. I have to say that this happened with the customer service from Spain, something that of course didn’t surprise me. We are used to this kind of “help” from customer services here.

So I tried to change the product information source to the official Plesk one but I noticed that the field was disabled, as it said “This field was locked by vendor.”.

Plesk-updates-source-and-installation-settings

I started to search for the original URL in /root/parallels in order to edit it with no luck. When I did a search for this problem on the Internet I got to the most surreal fix I’ve ever come around: Open the browsers devtools and remove the “disabled” option to the “URL to the directory with .inf3 file” input field, change the URL to the correct one (http://parallels.mirrors.ovh.net/parallels/) and click “Save”. It worked!

Plesk-updates-source-and-installation-settings-before

Plesk-updates-source-and-installation-settings-after

Ref: http://forum.odin.com/threads/where-is-the-parallels-installer-configuration-file.329704/#post-782253

Hide Mac OS X Recovery partition

Sometimes the Mac OS X Recovery partition can be seen because it’s mounted automatically on boot. This is usually caused because you moved the operating system to another disk (clone) or because you used an app that changed the disks partitions (rEFInd in my case).

Recovery HD

To fix this you can run this script:

#!/bin/bash

PARTITION=`mount | grep "Recovery HD" | awk '{print $1}'`
if [ -n "$PARTITION" ]; then
    sudo diskutil unmount $PARTITION
    sudo asr adjust --target $PARTITION -settype Apple_Boot
fi

Then SHUTDOWN (don’t just reboot) and turn on the computer.

You can also unmount that partition from the Disk Utility if you enable the debug option from the command line, but this will only work one time as it will be mounted again on next boot:

$ defaults write com.apple.DiskUtility DUDebugMenuEnabled 1

Disk-Utility-Debug

Ref: http://automatica.com.au/2013/11/hide-recovery-hd-after-cloning-an-os-x-installation/
http://osxdaily.com/2011/09/23/view-mount-hidden-partitions-in-mac-os-x/

Remove old Linux kernels in Ubuntu

As time goes new kernel versions are released. After a kernel update old installed versions are not removed automatically, they are keep in case something goes wrong so you can boot again to a previous version.

linux-penguin-logo

But you may end up having lots of old versions you’ll never use. To remove them first you need to find all the installed versions:

$ dpkg -l | grep linux-image | grep -v extra | awk '{print $2}'
linux-image-3.16.0-30-generic
linux-image-3.16.0-31-generic
linux-image-3.16.0-34-generic
linux-image-3.16.0-37-generic
linux-image-3.16.0-43-generic
linux-image-generic-lts-utopic

Then remove all the unwanted versions using apt-get autoremove:

$ sudo apt-get autoremove linux-image-3.16.0-30-generic linux-image-3.16.0-31-generic linux-image-3.16.0-34-generic

You should probably leave at least the latests 2 versions just in case.

Ref: https://help.ubuntu.com/community/Lubuntu/Documentation/RemoveOldKernels