Spring injection contenu d'un fichier texte

De EjnTricks

Lors de la construction d'un bean, il peut être utile de charger le contenu d'un fichier dans une variable d'un Bean, une classe Java. Spring va permettre de charger ce fichier par simple configuration. Ce principe a été mis en place pour configurer un message d'alerte lors de la connexion des utilisateurs à une application.

L'exemple utilise le mode de configuration par XML avec la version 3.2.10 de Spring, mais pourrait s'appliquer avec les annotations également. Le code source de l'article se trouve sur ici. L'illustration du chargement est disponible à partir du test unitaire SingletonClassTest.


Hand-icon.png Votre avis

Nobody voted on this yet

 You need to enable JavaScript to vote


Java format icon.png Définition bean

La première étape consiste à créer le bean qui contient une variable String dans laquelle est injecté le contenu du fichier texte.

package fr.ejn.tutorial.spring;

/**
 * String wrapper for Spring example to load a text file.
 * 
 * @author Etienne Jouvin
 * 
 */
public class MessageWrapper {

	private String message;

	/**
	 * @return the message.
	 */
	public String getMessage() {
		return message;
	}

	/**
	 * @param message the message to set.
	 */
	public void setMessage(String message) {
		this.message = message;
	}

}

Il n'y a donc rien de particulier dans ce bean, tout juste la variable message avec son couple de getter et setter.


Icon Personnalisation.png Contenu du fichier

Le fichier texte plainTextMessage.txt est placé à la racine des sources avec le contenu suivant.

File content.

L'objectif est donc de charger ce texte dans la variable message de la classe MessageWrapper


Définition Spring

Le fichier applicationContext.xml, chargé à l'initialisation de Spring, va permettre de définir une instance de MessageWrapper avec injection d'une valeur dans la propriété message.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
	default-lazy-init="false">

	<!-- Initialize logger, use log4j. -->
	<bean id="log4jInitialization" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
		<property name="targetClass" value="org.springframework.util.Log4jConfigurer"/>
		<property name="targetMethod" value="initLogging"/>
		<property name="arguments">
			<list>
				<value>classpath:log4j.properties</value>
			</list>
		</property>
	</bean>

	<!-- Bean to illustrate how to load text file. -->
	<bean id="messageBean" class="fr.ejn.tutorial.spring.MessageWrapper">
		<property name="message">
			<bean class="java.lang.String">
				<constructor-arg>
					<bean class="org.springframework.util.FileCopyUtils" factory-method="copyToByteArray">
						<constructor-arg value="classpath:plainTextMessage.txt" type="java.io.InputStream" />
					</bean>	 
				</constructor-arg>
			</bean>
		</property>
	</bean>	

</beans>

A première vue, la configuration est un peu complexe car cela implique plusieurs classes org.springframework.util.FileCopyUtils et java.lang.String ainsi que des méthodes spécifiques de celles-ci.

Mais en prenant le élément individuellement, la configuration paraît beaucoup plus claire. Dans un premier temps, la variable message est initialisée à l'aide d'un String.

	<!-- Bean to illustrate how to load text file. -->
	<bean id="messageBean" class="fr.ejn.tutorial.spring.MessageWrapper">
		<property name="message">
			<bean class="java.lang.String">
				.
				.
				.
			</bean>
		</property>
	</bean>

Donc une instance de la classe java.lang.String est injecté dans la variable message. Cette classe contient un constructeur avec un tableau de byte

    public String(byte bytes[], int offset, int length) {
        checkBounds(bytes, offset, length);
        this.value = StringCoding.decode(bytes, offset, length);
    }

Il suffit donc de charger le contenu du fichier dans un tel tableau et de le fournir en argument du constructeur du String. La classe org.springframework.util.FileCopyUtils contient la fonction copyToByteArray permettant d'effectuer ce chargement.

	public static byte[] copyToByteArray(File in) throws IOException {
		Assert.notNull(in, "No input File specified");
		return copyToByteArray(new BufferedInputStream(new FileInputStream(in)));
	}

	public static byte[] copyToByteArray(InputStream in) throws IOException {
		ByteArrayOutputStream out = new ByteArrayOutputStream(BUFFER_SIZE);
		copy(in, out);
		return out.toByteArray();
	}

Elle est donc utilisée afin de charger le fichier, dont l'emplacement est fourni en paramètre.

	<bean class="org.springframework.util.FileCopyUtils" factory-method="copyToByteArray">
		<constructor-arg value="classpath:plainTextMessage.txt" type="java.io.InputStream" />
	</bean>

A noter, l'utilisation de l'argument factory-method qui permet de spécifier la fonction à utiliser pour construire le bean, résultat de cette focntion.

Dans cet exemple, l'encoding du fichier n'est pas pris en compte. Mais il est tout à fait possible de le spécifier à l'aide des paramètres des différents constructeurs.