Archives pour la catégorie ‘Java’

Ant : génération d’un bundle OSGI avec bnd

Bnd : https://bndtools.ci.cloudbees.com/job/bnd.master/ws/biz.aQute.bnd/generated/

bhuisgen@muse:~/Projects/java/libirc$ cat build.xml
<target name="dist" depends="doc" description="create package">
   <!-- JAR package -->
   <mkdir dir="${dist.home}/bin/${ant.project.name}" />
   <copy todir="${dist.home}/bin/${ant.project.name}">
      <fileset dir="${build.home}" />
   </copy>
   <jar destfile="${dist.home}/${ant.project.name}-${build.version}-bin-${DSTAMP}.jar" basedir="${dist.home}/bin/" />

   <!-- OSGI bundle -->
   <replaceregexp file="myfile.bnd" match="Bundle-Version: (.*)" replace="Bundle-Version: ${build.version}" byline="true" />
   <taskdef resource="aQute/bnd/ant/taskdef.properties" classpath="${lib.home}/bnd-2.0.0.jar"/>
   <bnd classpath="${build.home}" files="myfile.bnd" output="${dist.home}/${ant.project.name}-${build.version}-bundle-${DSTAMP}.jar" />
</target>
bhuisgen@muse:~/Projects/java/libirc$ cat libirc.bnd
Bundle-Name: IRC Client Framework Bundle
Bundle-SymbolicName: fr.hbis.lib.irc
Bundle-Version: 0.2.0

Private-Package: fr.hbis.lib.irc.*

SWT : gérer le menu application sous MacOS X

SWT ne gère pas directement le menu application sous Mac OS X. Par défaut, toute application a donc un menu ressemblant à ceci :

Il est donc nécessaire de coder la modification du menu pour y refléter le nom réel de l’application et également mapper les actions des éléments A propos, Préférences et Quitter.

Auparavant, l’emploi de CocoaUIEnhancer était obligatoire car aucune API SWT n’existait pour accéder à ce menu. Depuis la version 3.7, les choses ont changé et une API interne est disponible. Voici un exemple d’utilisation de celle-ci :

Menu systemMenu = shell.getDisplay().getSystemMenu();
if (systemMenu == null)
	return; // not MacOS X

for (MenuItem menuItem : systemMenu.getItems())
{
	switch (menuItem.getID())
	{
		case SWT.ID_ABOUT:
		{
			menuItem.setText("About " + Constants.APPLICATION_NAME); // application name
			menuItem.addListener(SWT.Selection, new Listener()
			{
				@Override
				public void handleEvent(Event event)
				{
					helpAbout();
				}
			});
			break;
		}

		case SWT.ID_PREFERENCES:
		{
			menuItem.addListener(SWT.Selection, new Listener()
			{
				@Override
				public void handleEvent(Event event)
				{
					filePreferences();
				}
			});

			break;
		}

		case SWT.ID_QUIT:
		{
			menuItem.addListener(SWT.Selection, new Listener()
			{
				@Override
				public void handleEvent(Event event)
				{
					if (!fileExit())
						event.doit = false; // ignore exit if false
				}
			});

			break;
		}

		default:
		{
			break;
		}
	}
}

SWT : générer le JAR de la javadoc

La documentation de la librairie SWT n’est pas disponible directement sous la forme d’un package. Il faut donc la générer depuis les sources.

Une fois le JAR des sources récupéré sur cette page, la génération s’effectue de cette façon :

# cd swt-4.2-cocoa-macosx-x86_64
# unzip src.zip -d src
# javadoc -source 1.4 -d docs -sourcepath src -link http://java.sun.com/javase/6/docs/api/ -link . -subpackages org.eclipse.swt
# cd docs
# jar cf swt-4.2-doc.jar *

Reste ensuite à copier et ajouter le JAR à votre projet.

Par exemple sous Eclipse, il faut éditer les propriétés du projet, rubrique Java Build Path / Libraries et paramétrer l’élément Javadoc Location du JAR source :

Une fois tout ceci en place, la complétion de code doit être opérationnelle.

SWT : scrolling automatique avec un composant StyledText

L’astuce consiste à effectuer une sélection vide (invisible) du dernier caractère en appelant la méthode setSelection :

StyledText styledOutput;

// ...

styledOutput.append("texte à ajouter");

styledOutput.setSelection(styledOutput.getCharCount());

A noter qu’avec setSelectionRange, seul le positionnement du curseur est effectué pas le scolling.

Java : désactiver la validation d’un certificat SSL

Un moyen rapide et pas propre pour désactiver la validation d’un certificat SSL côté client :

SocketFactory socketFactory;
Socket socket;

TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
	public java.security.cert.X509Certificate[] getAcceptedIssuers()
	{
		return null;
	}

	public void checkClientTrusted(
			java.security.cert.X509Certificate[] certs,
			String authType)
	{
	}

	public void checkServerTrusted(
			java.security.cert.X509Certificate[] certs,
			String authType)
	{
	}
} };

try
{
	SSLContext sc = SSLContext.getInstance("TLS");
	sc.init(null, trustAllCerts, new java.security.SecureRandom());

	socketFactory = sc.getSocketFactory();
}
catch (GeneralSecurityException e)
{
	e.printStackTrace();
}

socket = socketFactory.createSocket(host, port);

Java EE : charger un fichier de propriétés depuis un WAR

	Properties properties = new Properties();

	try {
		properties.load(this.getClass().getClassLoader().
			getResourceAsStream("/config.properties));
	} catch (IOException e) {
		throw new RuntimeException(e.getMessage(), e);
	}

Le fichier de propriétés doit être stocké dans le CLASSPATH de l’application web. Dans le cas d’un WAR, il s’agit de WEB-INF/classes.

Java : caster un Object en Map

Alors le casse-tête du jour : comment convertir un Object en une Map ?

Solution avec dans mon cas une Map<Object,Object> – ce qui constitue toute la difficulté – :

Object ret;
Map<Object, Object> map;

ret = getData();
map = safeCastMap(ret, Object.class, Object.class);

Voici les fonctions de vérifications nécessaires  :

	@SuppressWarnings({ "unchecked" })
	public static <K, V> Map<K, V> safeCastMap(Object map, Class<K> keyType,
			Class<V> valueType) {
		checkMap(map);
		checkMapContents(keyType, valueType, (Map<?, ?>) map);
		return (Map<K, V>) map;
	}

	private static void checkMap(Object map) {
		checkType(Map.class, map);
	}

	private static <K, V> void checkMapContents(Class<K> keyType,
			Class<V> valueType, Map<?, ?> map) {
		for (Map.Entry<?, ?> entry : map.entrySet()) {
			checkType(keyType, entry.getKey());
			checkType(valueType, entry.getValue());
		}
	}

	private static <K> void checkType(Class<K> expectedType, Object obj) {
		if (!expectedType.isInstance(obj)) {
			throw new IllegalArgumentException("Expected " + expectedType
					+ " but was " + obj.getClass() + ": " + obj);
		}
	}

Java : itérer sur une Map « proprement »

Mauvaise méthode :

Map<Object,Object> map = getData();

for (Object key : map.keySet())
{
   System.out.println(key + "=" + map.get(key));
}

Bonne méthode :

Map<Object,Object> map = getData();

for (Map.Entry<Object,Object> entry : map.entrySet())
{
   System.out.println(entry.getKey() + "=" + entry.getValue());
}

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.

Haut de page