Archives pour la catégorie ‘Java’

Glassfish 3 : créer un pool de connexions JDBC

Cet exemple couvre la création d’un pool de connexions JDBC pour un serveur MySQL,

En premier lieu, ne pas oublier d’installer le driver JDBC de MySQL dans le domaine d’exécution :

$ cd $GLASSFISH_HOME
$ ./bin/asadmin stop-domain
$ cp ~/mysql-connector-java-5.1.13-bin.jar glassfish/domains/domain1/lib/
$ ./bin/asadmin start-domain

La création du pool de connexions (en veillant aux caractères d’échappement dans l’URL) :

$ ./bin/asadmin create-jdbc-connection-pool --datasourceclassname com.mysql.jdbc.jdbc2.optional.MysqlDataSource --restype javax.sql.DataSource --property User=myuser:Password=mypwd:URL=jdbc\\:mysql\\://127.0.0.1/mydb mydb_pool
Command create-jdbc-connection-pool executed successfully.

Un test rapide pour valider la connexion au serveur MySQL :

$ ./bin/asadmin ping-connection-pool mydb_pool
Command ping-connection-pool executed successfully.

Reste à créer la ressource jdbc/mydb à utiliser dans l’application Java :

$ ./bin/asadmin create-jdbc-resource --connectionpoolid=mydb_pool jdbc/mydb
Command create-jdbc-resource executed successfully.

Eclipse : utiliser votre script Ant depuis l’IDE

Pour utiliser votre script Ant depuis l’interface d’Eclipse, vous pouvez ajouter un Ant Builder à votre projet afin de remplacer le builder par défaut Java Builder. Une fois votre build.xml écrit, il faut configurer le builder Ant afin de faire correspondre les cibles aux actions de l’interface graphique : Build Project, Clean, Build Automatically

Pour ce faire, éditez les propriétés de votre projet et sélectionner la rubrique Builders. Ajoutez un builder de type Ant Builder et choisissez un nom lié au projet en cours (afin de pouvoir travailler sur plusieurs projets par la suite).

  • La première étape de configuration consiste à sélectionner votre fichier build.xml et son répertoire de travail.

  • Le second onglet permet de configurer le rafraîchissement du projet et de la vue Project Explorer, suite aux nouveaux fichiers  générés durant le build.

  • Les différents évènements de l’interface sont configurés dans l’onglet Targets :
    • After clean correspond au premier évènement de build lancé suite à un nettoyage par Build / Clean… La cible normale de compilation convient à cet usage.
    • Manual Build est levé par Build / Build Project. Si aucun évènement ne s’est produit suite au nettoyage, ce ne sera pas cet évènement qui sera levé mais After clean.
    • Auto-build correspond à l’évènement lancé par l’IDE lorsqu’une modification est détectée dans les sources (ou comment ruiner son disque dur rapidement). Vous pouvez le désactiver en ne spécifiant aucune cible ou le faire par l’interface en décochant Build / Build Automatically.
    • Clean correspond à la cible exécutée par Build / Clean…

Vous pouvez spécifier plusieurs cibles par évènement. Elles seront toutes exécutées par  ordre. Si  vos cibles ont des dépendances, elles seront également exécutées. Dans un tel cas, seule la dernière cible de la chaîne est nécessaire. Si aucune cible n’est sélectionnée, l’interface d’Eclipse ne répondra pas.

  • Dernier point, il faut désactiver le builder d’Eclipse Java Builder et confirmer l’avertissement.

Si vous souhaitez avoir un accès rapide à vos cibles secondaires, vous pouvez faire appel à la vue Ant et y ajouter vos scripts.

Java : JAX-WS & exception utilisateur

La gestion des exceptions utilisateur au sein d’un webservice utilisant l’API JAX-WS doit respecter quelques contraintes afin de  transmettre l’ensemble des informations au client SOAP.

Voici un exemple pour une classe d’exception UserFault dont les détails optionnels sont implémentés par la classe UserFaultDetail :

@WebFault
public class UserFault extends Exception {
	private static final long serialVersionUID = 1L;
	private UserFaultDetail userFaultDetail;

	/**
	 * Constructs an <code>UserFault</code> object.
	 *
	 * @param message
	 *            the error message.
	 * @param userFaultDetail
	 *            the error details.
	 */
	public UserFault(String message, UserFaultDetail userFaultDetail) {
		super(message);
		this.userFaultDetail = userFaultDetail;
	}

	/**
	 * Constructs an <code>UserFault</code> object.
	 *
	 * @param message
	 *            the error message.
	 * @param userFaultDetail
	 *            the error details.
	 * @param cause
	 *            the error cause.
	 */
	public UserFault(String message, UserFaultDetail userFaultDetail,
			Throwable cause) {
		super(message, cause);
		this.userFaultDetail = userFaultDetail;
	}

	/**
	 * Returns the error details.
	 *
	 * @return the error details.
	 */
	public UserFaultDetail getFaultInfo() {
		return userFaultDetail;
	}
}
public class UserFaultDetail {
	public static final int ERROR_UNKNOWN = 0;
	public static final int ERROR_INVALIDAPIKEY = -1;
	private int code;

	/**
	 * Constructs a new <code>UserFaultDetail</code> object.
	 */
	public UserFaultDetail ()
	{
		this.code = UserFaultDetail.ERROR_UNKNOWN;
	}

	/**
	 * Constructs a new <code>UserFaultDetail</code> object.
	 * @param code the code of the fault.
	 */
	public UserFaultDetail (int code)
	{
		this.code = code;
	}

	/**
	 * Returns the code of the fault.
	 * @return the code.
	 */
	public int getCode() {
		return code;
	}

	/**
	 * Sets the code of the fault.
	 *
	 * @param code
	 */
	public void setCode(int code) {
		this.code = code;
	}
}

Mac OS X : Java 6 pour Mac à CPU 32 bits

Le port de Java 6 pour les Macs à CPU 32 bits (Intel CoreDuo 2006) est disponible au téléchargement sur cette page :

http://landonf.bikemonkey.org/static/soylatte/

Java : analyse de code et détection de bugs

S’il y a bien un logiciel à conserver dans sa boite à outils, il s’agit d’un analyseur de code. En phase de stabilisation d’un de mes logiciels, j’en ai profité pour passer un coup de FindBugs!, l’analyseur et détecteur de bugs open-source pour Java. Il opère directement sur le byte-code à la recherche d’erreurs de programmation et si les sources sont disponibles, il marque son  endroit exact. Il dispose de son propre frontend graphique, mais un plugin Eclipse existe. L’intégration à un projet peut également se faire par le biais d’une tâche Ant.

Je me suis donc retrouvé avec à peu près 80 problèmes tous types confondus (sur les 40 000 lignes du projet, je trouve çà honnête), sachant qu’il y a toujours des faux-positifs (au nombre de 60). Pêle-mêle, il a réussi à détecter :

  • des nettoyages de ressources inutiles dans des blocs de traitement d’exception.
  • des itérateurs inadaptés par exemple lors d’une itération de Map, en me conseillant l’utilisation du bon (screenshot 1).
  • des problèmes de synchronisation d’ accès concurrents.
  • un bloc synchronized vide, dans mon cas un faux-positif (screenshot 2).
  • un appel à wait () hors d’une boucle d’itération, idem faux-positif.
  • l’utilisation de variables inutiles.

Bref, l’outil relève des faux-positifs – c’est quelque peu obligatoire – mais son utilité n’en n’est pas atteinte !

Site officiel : http://findbugs.sourceforge.net/
Source de téléchargement du plugin Eclipse : http://findbugs.cs.umd.edu/eclipse/
Autres outils du même type : MPD, CheckStyle…

findbugs_01findbugs_02

Java : loguer les exceptions avec un stacktrace

Un petit bout de code utile pour tout programme de type démon/serveur et qui permet d’enregistrer dans un fichier journal (cf. API java.util.logging) toute exception non gérée, en particulier avec son stacktrace complet, tel que Java le produirait en console :

private final static Logger m_logger = Logger.getLogger ("package.MyClass");

try
{
    [...]
}
catch (Exception exception)
{          
    StringBuilder stackTrace = new StringBuilder ("exception during execution: " +
        exception.getMessage ());

    for (StackTraceElement element : exception.getStackTrace ())
    {           
        stackTrace.append ("\n\tat " + element.getClassName ()
                + ":" + element.getMethodName () + "("
                + element.getFileName () + ":"
                + element.getLineNumber () + ")");
    }

    m_logger.log (Level.SEVERE, stackTrace.toString ());
}

Exemple d’output :

2 mai 2009 18:51:26 fr.hbis.ircs.Client parse
GRAVE: exception during command execution 'JOIN': fr.hbis.ircs.Channel.create(Ljava/lang/String;
    Ljava/lang/String;)Lfr/hbis/ircs/Channel;
    at fr.hbis.ircs.commands.Join:doCommand(Join.java:130)
    at fr.hbis.ircs.commands.Join:execute(Join.java:64)
    at fr.hbis.ircs.Client:parse(Client.java:158)
    at fr.hbis.ircs.Client:read(Client.java:127)
    at fr.hbis.ircs.nio.MessageTask:doProcess(MessageTask.java:253)
    at fr.hbis.ircs.nio.MessageTask:doRead(MessageTask.java:197)
    at fr.hbis.ircs.nio.MessageTask:doTask(MessageTask.java:152)
    at fr.hbis.ircs.lib.nio.task.TaskBase:run(TaskBase.java:102)
    at java.util.concurrent.ThreadPoolExecutor$Worker:runTask(ThreadPoolExecutor.java:885)
    at java.util.concurrent.ThreadPoolExecutor$Worker:run(ThreadPoolExecutor.java:907)
    at fr.hbis.ircs.lib.nio.worker.DefaultWorkerThread:run(DefaultWorkerThread.java:123)

Sympa, on en perd plus une miette.

Java : pense-bête JVM & options d’exécution

Un petit pense-bête concernant les différentes options d’exécution de la JVM étant donné que j’arrive pas les retenir.

Journalisation avec fichier de configuration custom pour l’API java.util.logging :

java [...] -Djava.util.logging.config.file=./logging.properties [...]

Monitoring avec jconsole :

en local :

java [...] -Dcom.sun.management.jmxremote [...]

à distance :

java [...] -Dcom.sun.management.jmxremote \
        -Dcom.sun.management.jmxremote.port=8001 \
        -Dcom.sun.management.jmxremote.authenticate=false \
        -Dcom.sun.management.jmxremote.ssl=false [...]

Remote debug JDPA :

avec JVM < 5.0 :

java [...] -Xdebug -Xrunjdwp:transport=dt_socket,server=y,address="8000" [...]

avec JVM >= 5.0 :

java [...] -agentlib:jdwp=transport=dt_socket,server=y,address="8000" [...]

Eclipse : Remote debugging avec JDPA

Parfois, il est indispensable de tester son application sous un environnement précis. Si cela ne tourne pas rond, un debug est nécessaire. Pour conserver les mêmes conditions d’exécution, un debug distant depuis son IDE est possible. Le principe est qu’une connexion réseau est faite entre le frontend du débogueur (IDE) et un backend au niveau de la JVM (JDPA, Java Debug Architecture). Deux méthodes sont possibles  :

  • « Socket attach » : une socket est en écoute au niveau de la JVM. L’IDE va s’y connecter pour contrôler le flux d’exécution et récupérer les informations de debug.
  • « Socket listen » : une socket est en écoute sur la machine de développement. Dans ce cas, la JVM s’y connecte pour ensuite être contrôlée.

Le choix entre les 2 méthodes dépend du filtrage réseau présent entre les 2 postes. Des options spécifiques sont donc à fournir à la JVM dont l’adresse IP / port de la socket et la méthode de remote debug.

Avec Eclipse, un remote debug par socket attach se fait ainsi :

  1. Compilation des sources avec les options de debug (sans blague)
  2. Déploiement / lancement de l’application sur la machine de test :
    java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000 [...]
  3. Lancer l’application depuis l’IDE avec une configuration de remote debug en précisant l’IP + port du serveur d’exécution : menu Run -> Debug … -> Remote Java Application.

Le reste s’effectue comme un debug traditionnel.

Screenshot 1 : lancement de la JVM d’exécution avec backend JDPA
Screenshot 2 : configuration debug avec l’IP/port du serveur d’exécution
Screenshot 3 : session de debug distante

eclipse_remotedebug-01eclipse_remotedebug-02eclipse_remotedebug-03

Haut de page