JavaScript : les bases du Langage

Netapsys Devoxx 2015

Netapsys Devoxx 2015

Le Devoxx France 2015 se tenait du 8 Avril au 10 Avril à Paris, au Palais des Congrès.

Cette plateforme est offerte aux développeurs principalement Java pour se retrouver et partager sur plusieurs sujets aux moyens de Conférences, Labs etc. Elle permet de prendre le pool de ce qui se fait dans le monde informatique en termes d’utilisation de Frameworks, d’Outils et de Best Practices.

Parcourir l'article

JSF2 – JavaServer Faces

Introduction

Quel Framework Web choisir lorsqu’on commence un nouveau projet Web en Java ? Comme vous le savez certainement, il en existe une panoplie. Eh bien, je vais essayer de vous rendre encore plus indécis sur ce choix en vous présentant Java Server Faces (JSF). Je plaisante, à la fin de cet article je préconiserai des types applications sur lequel JSF irait comme un gant.

Mise en place d’un WebService SOAP avec Apache CXF

Aujourd'hui pour mettre en place un webservice SOAP, il existe sur le marché différents frameworks: Axis, Spring WS et Apache CXF.

Si l'utilisation d'un framework comme Axis peut s'avérer assez fastidieuse, nous allons voir qu'avec Apache CXF, l'écriture de Webservices est très simplifiée.

Caractéristique

Le framework Apache CXF s'appuie sur la norme JAX-WS. Il supporte le mode "code-first", c'est-à-dire:  il autorise que le développeur commence par l'implémentation du webservice, avant la création du contrat d'interface.

Etude de cas

Nous allons implémenter un webservice qui va exposer un service d'addition. Il prendra en entrée 2 paramètres de type entier et retournera comme réponse la somme de ces 2 entiers.

Pré-Requis

Pour implémenter ce webservice, il faut être en moins en jdk 1.5.

Je vous conseille également d'utiliser maven pour récupérer les dépendances nécessaires.

Récupération des dépendances

Nous allons récupérer à l'aide de maven les librairies de cxf et de spring:

<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<version>2.5.5</version>
</dependency>

Implémentation

Nous allons déclarer l'interface de notre Webservice OperationService qui va contenir une méthode addition qui sera exposée:


package ideo.poc.cxf;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService
public interface OperationService {
@WebMethod
public int addition (int a, int b);
}

Les annotations @WebService et @WebMethod permettent respectivement de spécifier que l'interface exposée sera l'interface OperationService et que la méthode exposée sera la méthode addition.

Cette interface sera implémentée par la classe OperationServiceImpl, de la façon suivante:


package ideo.poc.cxf;
public class OperationServiceImpl implements OperationService{
public int addition(int a, int b) {
return a + b;
}
}

Il est intéressant de noter qu'avec l'utilisation des annotations, notre interface et notre classe n'ont besoin d'aucune adhérence avec un framework tiers (aucun hétitage n'est nécessaire).

Configuration

Il reste à configurer 2 fichiers:

- le fichier applicationContext.xml utilisé par Spring (localisé dans le répertoire webapp/WEB-INF):

Il faut d'abord importer le context propre à CXF pour déployer le web service de la façon suivante:


<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

Puis il faut déclarer le "end-point", c'est-à-dire le point d'entrée de notre webservice. Dans notre cas il s'agira de la classe OperationServiceImpl:


<jaxws:endpoint id="oprationService"
implementor="ideo.poc.cxf.OperationServiceImpl"
address="/OperationService" />

- le fichier web.xml (localisé dans le répertoire webapp/WEB-INF) qui va notement déclarer une servlet provenant du framework CXF:


<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>democxf</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

Test du webservice

Une fois le war généré et déployé dans un serveur d'application, en tappant l'URL  http://localhost:8080/OperationService?wsdl, nous pouvons voir le WSDL généré:

Il ne nous reste plus qu'à tester notre webservice.

Dans un navigateur, en invoquant l'URL http://localhost:8080/OperationService/addition?arg0=1&arg1=2

Nous avons le résultat suivant:

Sources

Vous trouverez les sources de l'exemple ici .

Conclusion

Apache CXF est un framework qui permet d'écrire de façon très souple des Webservices SOAP par rapport à ces concurrents.

Si votre projet utilise Java 5, je vous conseille fortement ce framework pour le déploiement de Webservice.

Spring Batch par l’exemple

Qu'est-ce que Spring-Batch?

Spring-Batch est un framework développé en collaboration par SpringSource et Accenture.

Il permet de palier à des problème récurrents lors de développement de batchs:
- productivité
- gestion de gros volumes de données
- fiabilité
- reinvention de la roue .

Il s'agit donc d' un framework fournissant un outillage complet, adapté à l'écriture des batchs.

Pour rappel dans le monde informatique, un batch est un programme fonctionnant en StandAlone, réalisant un ensemble de traitements sur un volume de données.

Architecture de Spring-Batch

L'architecture de Spring-Batch est constituée en 2 couches:

- la couche Batch Core
- la couche Batch Infrastructure

La couche "Batch Core" contient une API permettant de lancer, monitorer et de gérer un batch.
Les principales interfaces et classes que contient l'API sont: Job, JobLauncher et Step.
Schématiquement un batch correspond à un job qui va être lancé via un JobLauncher.

Un job est constitué d'une ou plusieurs Step. Une Step correspond à une étape dans un batch.

La couche "Batch Infrastructure" contient un API fournissant comme principales interfaces: ItemReader, ItemProcessor et ItemWriter.

Etude de cas

Admettons que nous voulions traiter le fichier texte suivant:

1,DUPONT,Philippe,M
2,DUPUIS,Marie,Mme
3,DURAND,Guillaume,M
4,MARTIN,Cyril,M
5,MICHEL,Sophie,Mme
6,MERCIER,Muriel,Mme
7,VIDAL,Thomas,M
8,JACKSON,Michael,M
9,BROWN,Michele,Mme
10,WILLIAMS,Venus,Mme

Il s'agit d'un fichier plat contenant 10 enregistrements de personnes, dont les informations sont séparées par le caractère "," .

Les informations sont dans l'ordre: l'id de la personne, le nom, le prénom et la civilité.

Nous voulons que notre batch enregistre les personnes en base de données uniquement si leur civilité à la valeur "M".

Mise en place du projet

Base de données

Pour cela, je vais utiliser une base MySQL, et je vais créer une table PERSONNE ayant la structure suivante:

CREATE TABLE PERSONNE (ID INTEGER,

NOM VARCHAR (50),

PRENOM VARCHAR (50),

CIVILITE VARCHAR (3),

PRIMARY KEY (ID)

);

Récupérer Spring Batch

Pour récupérer les différentes bibliothèques, je vous conseille de passer par un projet Maven.

Avec Maven 2, il faudra récupérer les dépendances de Spring Batch de la façon suivante dans le fichier pom.xml:

<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-core</artifactId>
<version>2.1.8.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-infrastructure</artifactId>
<version>2.1.8.RELEASE</version>
</dependency>

Implémentation du batch

La classe Personne

Cette classe est un JavaBean qui va encapsuler les données d'une personne lue à partir du fichier texte.

Cette classe s'écrit de la façon suivante:


public class Personne {

private int id;
private String nom;
private String prenom;
private String civilite;
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
public String getPrenom() {
return prenom;
}
public void setPrenom(String prenom) {
this.prenom = prenom;
}
public String getCivilite() {
return civilite;
}
public void setCivilite(String civilite) {
this.civilite = civilite;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}

Définition de l'ItemReader

Spring Batch fournit des implémentation de l'interface ItemReader notement pour parser des fichier plats et des fichiers XML.

Notre reader va être déclaré dans le fichier de configuration de la façon suivante:


<bean id="personneReaderCSV" class="org.springframework.batch.item.file.FlatFileItemReader" >
<property name="resource" value="input/personnes.txt" />
<property name="lineMapper">
<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<property name="lineTokenizer">
<bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="delimiter" value=","/>
<property name="names" value="id,nom,prenom,civilite" />
</bean>
</property>
<property name="fieldSetMapper">
<bean class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
<property name="targetType" value="ideo.springbatch.poc.Personne" />
</bean>
</property>
</bean>
</property>
</bean>

Dans cette configuration nous précisons que:

- la classe FlatFileItemReader (pour lire un fichier plat) sera utilisée comme ItemReader pour lire notre fichier,

- le séparateur de champ est le caractère ","

- chaque ligne est composée des champs: id,nom,prénom et civilité

- toutes ces informations seront stockées dans la classe Personne.

Nous avons donc définit notre reader sans rien coder! Bien sûr, il est possible de définir notre propre implémentation de l'interface ItemReader.

Définition de l'ItemProcessor

C'est dans l'ItemProcessor qu'il y aura la place pour implémenter les règles de gestion de notre batch.

Notre classe d'implémentation sera écrite de la façon suivante:

public class PersonProcessor implements ItemProcessor<Personne, Personne>{

public Personne process(final Personne personneInput) throws Exception {

Personne personneOutput = null;

//si la civilite a la valeur M la personne sera ecrite en base sinon on la  rejette

if ("M".equals(personneInput.getCivilite())) {

personneOutput = new Personne();

personneOutput.setCivilite(personneInput.getCivilite());

personneOutput.setId(personneInput.getId());

personneOutput.setNom(personneInput.getNom());

personneOutput.setPrenom(personneInput.getPrenom());

}

return personneOutput;

}

Puis dans le fichier de configuration, l'ItemProcessor sera définit de la façon suivante:


<bean id="personProcessor" class="ideo.springbatch.poc.PersonProcessor" />

Définition de l'ItemWriter

L'ItemWriter va persister les données qui ont été traitées via l'ItemProcessor. Dans cet exemple je vais sauvegarder les données en base de données dans la table PERSONNE, en utilisant le template jdbcTemplate fournit par Spring.

Ce qui va donner dans la classe d'implémentation:


@Transactional (propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
public class PersonJdbcWriter implements ItemWriter<Personne>{
private JdbcTemplate jdbcTemplate;
private static final String REQUEST_INSERT_PERSONNE = "insert into PERSONNE (id,nom,prenom,civilite) values (?,?,?,?)";
private static final String REQUEST_UPDATE_PERSONNE = "update PERSONNE set nom=?, prenom=?, civilite=? where id=?";
public void write(List<? extends Personne> items) throws Exception {
for (Personne personne : items) {
final Object object [] = {personne.getNom(),personne.getPrenom(), personne.getCivilite(),personne.getId()};
//on tente un update
int nbLigne = jdbcTemplate.update(REQUEST_UPDATE_PERSONNE, object);
//si le nombre de ligne mise a jour vaut 0, on fait un insert
if (nbLigne == 0) {
final Object object2 [] = {personne.getId(),personne.getNom(),personne.getPrenom(), personne.getCivilite()};
jdbcTemplate.update(REQUEST_INSERT_PERSONNE, object2);
} else {
}
}
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}

}

Dans le fichier de configuration Spring, l'ItemWriter sera définit de la façon suivante:


<bean id="personDaoWriter" class="ideo.springbatch.poc.PersonJdbcWriter" >
<property name="jdbcTemplate" ref="idJdbcTemplate" />
</bean>

Définition du job

Le job sera défini de la façon suivante:


<job id="importPersonnes"
xmlns="http://www.springframework.org/schema/batch">
<step id="readWritePersonne">
<tasklet>
<chunk reader="personneReaderCSV" writer="personDaoWriter" processor="personProcessor" commit-interval="2" />
</tasklet>
</step>
</job>

Notre job sera donc constitué d'une seule Step dont la tasklet est de type "Chunk".

Le chunk est un concept important dans Spring Batch qui définit l'enchainement qui va s'executer dans une transaction.
Le chunk aura comme propriétés l'item reader, l'item processor et l'item writer définit plus haut.
Le paramètre commit-interval du chunk définit le nombre d'items qui va être stocké en mémoire avant d'être persistés.

Pour executer notre batch il suffit de lancer le programme main suivant:

public class BatchPersonne {

public static void main (String [] args) throws Exception {

ClassPathXmlApplicationContext cpt = new ClassPathXmlApplicationContext("batch-context.xml");

cpt.start();

JobLauncher jobLauncher = (JobLauncher) cpt.getBean("jobLauncher");

Job job = (Job) cpt.getBean("importPersonnes");

JobParameters parameter = new JobParametersBuilder().addDate("date", new Date())

.addString("input.file", "C:/envdev/travail/in/personnes.txt").toJobParameters();

jobLauncher.run(job, parameter);

}


}


Sources

Les sources complètes du projet sont disponible via l'URL suivante:http://public.ideotechnologies.com/blog/SpringBatch-POC.zip

Conclusion

Nous avons vu à travers cet exemple peut paraître complexe au premier abord, surtout sur l'aspect configuration.

Il a néanmoins le mérite d'apporter les avantages suivants:

- fourniture d'un framework ouvert adaptée dans l'écriture de batch
- moins de code à écrire, donc une meilleur productivité et une meilleur maintenabilité
- on récupère l'outillage de Spring (transaction, injection de dépendance, test unitaire etc ...)

De plus Spring Batch présente des fonctionnalités avancées assez intéressantes:

- gestion de la reprise sur erreur
- possibilité de "skipping"
- possibilité de parallélisation

Spring Batch est donc un framework complet, robuste et stable.
Malgré sa complexité, il peut s'avérer interessant dans le cadre de batchs devant traiter de gros volumes de données.

Référence

Java et la gestion de la mémoire

Les problèmes de performance  les plus couramment rencontrés en Java peuvent provenir de quatre causes :

  • Le code de l'application
  • L'environnement sur lequel s'exécute l'application (serveur d'application, jvm, os)
  • Dépendances externes (base de données, web services, ...)
  • Charge excessive

Les causes ci-dessus sont données dans l'ordre de leur probabilité d'occurrence.

Il faut bien comprendre que l'upgrade du serveur physique n'intervient qu'en dernier lieu ! En effet, La cause est souvent logicielle avant d'être matérielle.

Dans ce billet, je vais rentrer plus en détail sur l'optimisation de la JVM Sun et plus particulièrement sur la gestion de la mémoire.

Recherche « plein texte » vs. recherche « classique »

Dans une application, le besoin de réaliser des recherches se fait régulièrement sentir. La manière classique de répondre à ce besoin est de proposer un écran de recherche proposant un certain nombre de critères, techniquement traduit par une requête en base de données.

Ce type de recherche aboutit à une grande complexité des requêtes de recherche :

  • Clause select de n colonnes
  • Clause where avec jointure de m tables
  • Clause like afin de gérer les recherches de mots partiels
  • ...

Ces requêtes permettent d’effectuer des recherches sur des critères précis, mais ont leurs limites. En effet, avec les moteurs de recherche sur internet tels que Google, les utilisateurs ont pris l’habitude d’effectuer des recherches sur des mots clés et d’obtenir des résultats prenant en compte des variantes des mots clés et classés par pertinence.