Geek, alcool et rock'n'roll

Aller au contenu | Aller au menu | Aller à la recherche

lundi 12 juillet 2010

MySQL Connector, GPL, et autres licences

Chouette, se disent mes lecteurs, encore un billet geek !

Aujourd'hui, je vais partager avec vous des problèmes de licences. Je me pose certaines questions concernant la contamination[1] de la GPL.

Tout ça a commencé avec l'utilisation d'un connecteur MySQL. Le connecteur MySQL, c'est ce bout de code qui permet à une application d'accéder à une base de données MySQL. Ce connecteur est sous licence GPL, avec une exception pour d'autres licences Open Source, le but étant qu'un logiciel Open Source peut utiliser le connecteur même si sa licence n'est pas compatible avec la GPL.

Évidemment, en entreprise, on ne veut pas forcément ouvrir son code en Open Source. Dans le cas de MySQL, généralement ça ne pose pas de problème, car ça reste côté serveur et il n'y a pas redistribution. Mais dès lors qu'il y a redistribution (vers des filiales par exemple), le problème se pose.

Le connecteur C

On va parler d'abord du connecteur C, car c'est le plus simple à aborder du point de vue des licences : si on l'utilise, on doit se lier avec, et donc la GPL doit s'appliquer. Dès lors, si on veut distribuer un logiciel en C (ou C++) qui a besoin d'une base de données, il y a peu de choix :

  • soit on achète une licence à MySQL[2],
  • soit on change de base de données, par exemple PostgreSQL[3], qui est sous une licence similaire à BSD.

Le connecteur Java

On va corser un peu et parler du connecteur Java.

En Java, on utilise une interface bien pratique qui s'appelle JDBC. Cette interface est implémentée par tous les connecteurs de base de données, ce qui permet très facilement de passer d'une base à une autre. Évidemment, il va exister des différences dans les implémentations, ne serait-ce que dans le SQL à utiliser, mais l'API est identique. JDBC permet un découplage entre la bibliothèque GPL et l'application qui l'utilise.

Il y a deux manières d'utiliser un connecteur JDBC : soit directement, soit, dans le cas d'une application JEE, par le conteneur JEE.

Utilisation directe

Dans ce cas, même s'il y a découplage par JDBC, je pense qu'on rentre dans le champ de la GPL. En effet, on va spécifiquement ajouter le connecteur dans le classpath de l'application, et généralement on va même l'embarquer avec les autres bibliothèques utilisées. Et on va même nommer directement le Driver spécifique à ce connecteur. Pour le connecteur MySQL, ça se fait ainsi :

Class.forName("com.mysql.jdbc.Driver");

On peut évidemment exporter cette chaîne de caractères dans un fichier de configuration, pour découpler un peu plus, mais j'ai l'impression que c'est noyer le poisson.

Utilisation dans le cadre du serveur d'application

Dans un serveur d'application, c'est le serveur qui va fournir la connexion à la base de données. En principe, l'application ne sait pas particulièrement où elle est connectée, et à qui. Ainsi, à mon sens, l'application peut utiliser le connecteur GPL dans ce cas... puisqu'elle ne sait même pas qu'elle l'utilise[4].

On est pourtant dans ce que j'appelle une zone grise, car c'est pas très clair tout ça. Dans une telle application, on va tout de même avoir des requêtes SQL spécifiques à MySQL. Ou bien on va configurer Hibernate en lui disant qu'on utilise un connecteur MySQL. Des trucs comme ça qui sont autant d'indices qu'on est bien adhérent à MySQL, que l'application ne fonctionnera pas sans connecteur, que donc la licence GPL s'applique, et qu'on a donc pas le droit d'utiliser la bibliothèque.

Et dans PHP ?

PHP, c'est commode, vient avec son client MySQL. Ce client MySQL est bien sûr implémenté en utilisant le connecteur C vu plus haut[5].

Dès lors, une application PHP qui n'est pas GPL ou dans une licence Open Source concernée par l'exception a-t-elle le droit d'utiliser directement le client MySQL de PHP ? Et si elle passe par une bibliothèque d'abstraction comme PDO ?

Conclusion

J'en n'ai pas vraiment. Je dirais juste que la GPL, c'est assez facile à appliquer dans le monde des programmes compilés (et encore, avec les chargements dynamiques de bibliothèques, ça peut devenir aussi compliqué). Mais dans le monde des langages interprétés (ou entre les deux, comme Java), c'est plus difficile.

Et vous, vous avez un avis ?

Notes

[1] Ou l'incompatibilité, pour éviter le terme de "contamination".

[2] C'est bien, car on participe ainsi à son développement.

[3] C'est bien aussi, car c'est à mon avis la meilleure base de données Open SOurce.

[4] Dans ce cas, quelqu'un est-il hors-la-loi ? Celui qui déploie l'application ?

[5] Je viens de lire que PHP a fait leur propre client MySQL. Dans ce cas, ça ne s'applique sans doute pas.

mardi 6 juillet 2010

Intégrer Jackson avec CXF 2.2

Bonjour à tous,

Et oui, encore un billet technique, désolé à mes lecteurs non-geeks ;-)

Aujourd'hui, en effet, je me suis pris le chou avec CXF. J'espère que ça pourra être utile à d'autres ;-)

Le contexte : JAX-RS et CXF

À tort ou à raison, on utilise CXF comme implémentation JAX-RS. JAX-RS, c'est une spécification Java pour pouvoir faire du REST. CXF utilise Jettison comme sérialiseur JSON. Or, Jettison s'appuie sur JAXB[1], ce qui est bien pratique pour le développeur, mais tout pourri pour ce qui est du JSON produit[2].

Jackson : le sérialiseur JSON idéal

C'est là qu'intervient jackson. Je crois que c'est aujourd'hui le meilleur sérialiseur JSON pour Java. Et en plus, il y a plein de docs pour le faire fonctionner avec JAX-RS. Sauf qu'en fait, ça marche pas[3].

La solution avec Spring

Voici la solution trouvée, dans un fichier de contexte Spring :

<jaxrs:server id="monBeauServiceRest" address="/service">
  <jaxrs:serviceBeans>
    <ref bean="monBeanRest" />
  </jaxrs:serviceBeans>
  <jaxrs:providers>
    <ref bean="jsonProvider"/>
  </jaxrs:providers> 
</jaxrs:server>

<bean id="jsonProvider" class="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider">
</bean>

Notes

[1] La spécification Java pour faire du XML facilement.

[2] Notamment, les tableaux/collections sont sérialisés différemment en fonction de leur contenu. Pratique.

[3] Ou alors ça marche peut-être en JAX-RS 1.1 implémenté par CXF 2.3 pas encore sorti. Ou avec Jersey.

mardi 22 décembre 2009

Debian, Java et IPV6

J'ai décidé hier de mettre à jour la Debian de mon PC du boulot.

Globalement, ça s'est bien passé. Il y a eu cependant deux problèmes majeurs : VMWare ne se lance plus, et j'en parlerai dans un autre billet si j'arrive à résoudre le problème, et Eclipse me retournait un joli "network unreachable" dès que j'essayais d'accéder au gestionnaire des plug-ins.

J'ai d'abord réalisé un petit programme Java, pour vérifier que c'était bien tout Java qui était concerné :

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

public class TestReseau {
	public static void main(String[] args) throws MalformedURLException,
			IOException {
		URLConnection connection = new URL("http://www.google.fr")
				.openConnection();
		BufferedReader reader = new BufferedReader(new InputStreamReader(
				connection.getInputStream()));

		StringBuilder sb = new StringBuilder();
		String line;

		while ((line = reader.readLine()) != null) {
			sb.append(line + '\n');
		}

		System.out.println(sb.toString());
	}
}

Et, oui, que ce soit avec Java 5, Java 6, ou OpenJDK, le même problème apparaissait.

Une recherche rapide m'a amené sur le bug tracker Debian, avec la solution :

  • modifier /etc/sysctl.d/bindv6only.conf, nouveau fichier amené par la version 4.38 de netbase,
  • changer la valeur de net.ipv6.bindv6only vers 0,
  • et recharger procps par /etc/init.d/procps restart.

C'est très pénible de perdre une heure sur des changements silencieux comme ça, mais au moins, j'ai trouvé la solution... pas comme avec VMWare.

Mise à jour : il y a eu aussi un ptit bug avec Eclipse avec un GTK récent. Rapidement résolu en utilisant la variable d'environnement préconisée : GDK_NATIVE_WINDOWS=1. Le problème était que les contrôles ne répondaient pas toujours correctement (genre les boutons-poussoirs restaient appuyés quand on cliquait dessus, sans produire d'effet).