mercredi 9 mars 2011

RIF JAVA USER GROUP

Je viens de mettre en place le site web pour "RIF JAVA USER GROUP", que je rappel qu´il s´agit du premier JUG pour la communauté Rifine, dont le rôle principal est d´aider les gens dans le langage de programmation JAVA, des séminaires seront également organisés à côté des formations gratuites.

Le site est accessible via le lien suivant : http://rifjug.kenai.com.

J´encourage les Rifins à rejoindre ce site communautaire, et d´y participer d´avantage.

mardi 28 décembre 2010

Tutoriels Android

Joyeux Noël à tous !

Je suis penché ces derniers jours sur l’écriture d'un tutoriel sur Android, l'OS de Google pour les téléphones portables. Il s'agit en fait un tutoriel pour les débutants, mais d'autres tutoriels abordant des techniques plus avancées serons publiés dans un future proche.

Je vous invite à me proposer quelques thèmes dont je vais écrire dessus.


samedi 25 décembre 2010

Je suis committer au projet Faceboard

Le 22/10/2010:
Je viens d'être accepté par Nicolas Pihan dans le projet Faceboard, il s'agit d'une application Java/Swing permettant de s'interfacer avec Facebook, sans besoin d'y accéder par le biais d'un Browser.

Nous avons plein d'idées, dont nous espérons de produire une application de très haute qualité, notamment l’intégration de JavaFX, tout en le mixant avec les composants Swing, qui nous propose quelques effets, et surtout il y est ajouté un type de donnée nommé Duration, visant à créer des variables temporelles qui ont des valeurs de type ms, s, m, et h, servant à implémenter les animations.

Nous allons également, introduire le IoC par Google Guice, qui va nous permettre de développer une application modulaire, et pourquoi pas du OSGi.

Bon, je vous invite à contribuer à cette application, qui va être une véritable école.

samedi 11 décembre 2010

iBatis dans un contexte multi-utilisateur grâce à la technique Optimistic locking

Dans les logiciels en réseau, dont l'utilisation est soumise à de nombreux utilisateurs l'utilisant en même temps, sauvant le problème d’accès concurrent est évoqué.
Dans cet article je vais vous montrer comment implémenter un tel mécanisme en iBatis, dont il n y a pas de standard comme le cas d'hibernate, alors il faut l’implémenter par soit même comme suite :
  • Implémenter son propre OptimisticLockException qui doit dérivé RuntimeException ou réutiliser celui du Package JPA : javax.persistence.
  • Ajouter une colonne nommée version de type numérique non nulle dans la table et définir sa default value à 1.
  • Ajouter un champs nommé version à la classe de type int.
  • Modifier l'interface DAO pour déclencher une OptimisticLockException comme suite :
      public interface EntityDao {
           void createEntity(Entity entity);
           Entity selectEntryById(Long id);
           void updateEntity(Entity entity) throws OptimisticLockException;
           void deleteEntity(Entity entity);
     }
  • Modifier la classe DAO pour traiter les champs version

   public class EntityDaoImpl extends SqlMapClientDaoSupport implements EntityDao {

     @Override
     public void createEntity(final Entity entity) {
         getSqlMapClientTemplate().insert("insertEntity", entity);
         entity.setVersion(1);
     }


     @Override
     public Entity selectEntryById(final Long id) {
        return (Entity) getSqlMapClientTemplate().queryForObject("findEntityById", id);
     }


    @Override
    public void updateEntity(final Entity entity) throws OptimisticLockException {
        final int oldVersion = entity.getVersion();
        final int newVersion = oldVersion + 1;

        final Map params = new HashMap();
        params.put("entity", entity);
        params.put("oldVersion", oldVersion);
        params.put("newVersion", newVersion);

        int updateCount = getSqlMapClientTemplate().update("updateEntity", params);

        if (updateCount == 0) {
             throw new OptimisticLockException("Erreur lors de la mise à jour, un autre utilisateur est entrai de modifier cet enregistrement, veuillez valider vos modification plus tard ");
        }

        entity.setVersion(newVersion);
    }


    @Override
    public void deleteEntity(Entity entity) {
        getSqlMapClientTemplate().delete("deleteEntity", entity);
    }
  }

  • Modifier le fichier de configuration d'iBatis

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap>

 <typeAlias alias="Entity" type="votrePackage.domain.Entity"/>

 <resultMap id="EntityMap" class="Entity">
     <result column="id" property="id"/>
     <result column="value" property="value"/>
     <result column="version" property="version"/>
 </resultMap>

 <insert id="insertEntity" parameterClass="Entity">
     INSERT INTO entity (id, value, version) VALUES (#id#, #value#, 1)
 </insert>

 <select id="findEntityById" parameterClass="java.lang.Long" resultClass="Entity" resultMap="EntityMap">
         SELECT id, value, version FROM entity WHERE id=#value#
 </select>

 <update id="updateEntity" parameterClass="java.util.Map">
     UPDATE entity
     SET
         value=#entity.value#
         version=#newVersion#
     WHERE
         id=#entity.id#
         AND version=#oldVersion#
 </update>

 <delete id="deleteEntity" parameterClass="Entity">
     DELETE FROM entity WHERE id=#id#
 </delete>

</sqlMap>

Et voilà votre entité est prête à être utiliser dans un contexte multi urilisateur.

N'hésitez pas à me laisser vos commentaires.

Attractive JTable

Dans le présent article je vais vous montrer comment créer une JTable totalement attractive (jolie).
Dans un premier temps, vous devez récrire votre DefaultTableCellRenderer qui est le responsable d'afficher les lignes de notre JTable bel et bien nous somble, d'y ajouter des bouton, des JComponents, des images ...

Alors dans un premier temps vous devez Copier/Coller le code suivant dans un fichier nommé XTableCellRenderer :



import com.jgoodies.forms.factories.Borders;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;


/**
 *
 * @author Arafat Bouchafra
 * @Date 1 sept. 2010
 * @Time 01:23:40
 */
public class XTableCellRenderer extends DefaultTableCellRenderer {


    private JLabel renderer;
    private boolean left, right;


    public XTableCellRenderer(boolean left, boolean right) {
        this.left = left;
        this.right = right;
    }
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, final int row, int column) {
        if (renderer == null) {
            renderer = new JLabel() {


                @Override
                protected void paintComponent(Graphics g) {
                    Graphics2D g2d = (Graphics2D) g.create();


                    Boolean selected = (Boolean) getClientProperty("table.selected");
                    if ((selected != null) && (selected.booleanValue())) {
                        g2d.setPaint(new LinearGradientPaint(0, 0, 0, getHeight(),
                                new float[]{0f, 0.48f, 0.481f, 1f},
                                new Color[]{new Color(135, 155, 187), new Color(35, 77, 145), new Color(6, 47, 117), new Color(31, 66, 131)}));
                    } else {
                        Integer row = (Integer) getClientProperty("table.row");
                        if (row == null) {
                            row = 0;
                        }
                        Color c = (row % 2 == 0) ? new Color(98, 100, 99) : new Color(83, 85, 84);
                        g2d.setColor(c);
                    }


                    g2d.fillRect(0, 0, getWidth(), getHeight());


                    if (left) {
                        g2d.setColor(new Color(148, 148, 146));
                        g2d.drawLine(0, 0, 0, getHeight());
                    }


                    g2d.dispose();


                    super.paintComponent(g);
                }
            };
            renderer.setFont(new Font("Arial", Font.PLAIN, 10));
            renderer.setForeground(Color.WHITE);
            renderer.setBorder(Borders.DLU4_BORDER);
            renderer.setOpaque(false);
        }
        renderer.putClientProperty("table.selected", isSelected);
        renderer.putClientProperty("table.row", row);
        if (value != null) {
            renderer.setText(value.toString());
        } else {
            renderer.setText("");
        }
        return renderer;
    }
  
}


Vous aurez impérativement besoin de télécharger le jar forms depuis ici, puis au niveau de votre table utiliser le code suivant : 

        table = new JTable(model);
        for (int i = 0; i < table.getColumnCount(); i++) {
            final boolean left = (i > 0);
            final boolean right = (i < table.getColumnCount() - 1);

            table.getColumnModel().getColumn(i).setCellRenderer(new XTableCellRenderer(left, right));
        }
        table.setShowGrid(false);
        table.setRowHeight(20);
        table.setRowMargin(0);
        table.setIntercellSpacing(new Dimension(0, 0));

        table.setGridColor(Color.BLACK);

        //tcol = table.getColumnModel().getColumn(3);
        //tcol.setCellRenderer(new MyTableCellRenderer());

        table.setBackground(Color.darkGray);
        table.setForeground(Color.white);
        table.setSelectionBackground(new Color(0x54A4DE));
        table.setSelectionForeground(Color.white);
        table.setOpaque(false);
        table.setFont(new Font("Helvana", Font.BOLD, 12));
        table.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent e) {
                // TODO Auto-generated method stub
                //if(e.getClickCount() == 2)
                mouseDoubleClicked(e);
            }
        });

        scroll = new JScrollPane();
        scroll.getViewport().setOpaque(false);
        scroll.getViewport().setView(table);
        scroll.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 6, 1));
             scroll.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        scroll.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        scroll.setOpaque(false);
        scroll.setViewportView(table);

N'oubliez pas de me laisser vos commentaires si quelque chose ne marche pas !

Finalement je remercie ceux qui ont attendu la publication de cet article, et je leurs demandes de m'excuser ;-)

samedi 4 décembre 2010

Lancement du RIF Java User Group

Je viens de lancer le projet RIF Java User Group, qui aura comme objectif d'encadrer les programmeur Rifin dans le cadre de développement d'application en Java, il contiendra des articles, des tutoriels, des exemples, voir même des webcast, en essayera d'organiser des conférence, des séminaires, et des compétitions.


vendredi 3 décembre 2010

Créer des GUI en Swing totalement découplés par Spring IoC

Les possibiltés offertes par le Framework Spring dans le cadre de développement des applications Swing sont peut mises en évidence, comparaiment à celles du web. Que ce qu'offre Spring dans ce contexte ? Nous allons dans ce tutoriel voir un exemple concret étape par étape, et ainsi en déduire notre conclusion.
Jetons un coup d'oeil  sur la structure finale de notre application :


Comme vous pouvez le constater nous utilisons la bibliothèque spring-2.5.jar que vous pouvez télécharger depuis le site web : www.springsource.org, ainsi que commons-loggin.jar qui va servir pour les logs. Notez aussi l’existence de quelques composants Swing ordinaires tel que : JButton, JTextField, JPanel et bien sûr JFrame, nous avons aussi un ActionListener qui va être ajouté à notre bouton. Chacune des classes commençant par My hérite d'un composant Swing, donc rien de spécial, sauf les deux fichiers SpringLauncher.java qui va servir pour lancer notre application en utilisant des classes spécifique à Spring en appelant le fichier de configuration app-context.xml. Au démarrage notre application aura l’aspect suivant :


C'est un résultat pertinent. Les composant Swing ne font aucune chose de spécial. Le point ici est d'ajouter tout simplement des composant Swing à l'application sans ajouter aucun code java le rendant possible. Normalement à l’absence de Spring sa doit être fait avec du code Java, en ajoutant le JPanel à JFrame à l'aide de la méthode add,  et d'ajouter JButton, JTextField au JPanel de la même manière. Dans notre cas nous ne procéderons pas ainsi. En fait aucune classe n’appellera l'autre, elles sont toutes indépendant, elles sont découplées, dont voici le code de MyJFrame :



package springSwinging;
import java.awt.Dimension;
import javax.swing.JFrame;
/**
 *
 * @author Arafat Bouchafra
 * @Date   2 déc. 2010
 * @Time   03:00:34
 */
public class MyJFrame extends JFrame {
    public void init() {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
                setSize(new Dimension(300, 300));
                setVisible(true);
            }
        });
    }
}


Les autres classes sont similaires, ne délivrons que le code spécifique à chaque composant Swing définissant. L’évènement ActionListener est découplé, l'ActionListener n'est pas ajouté à JButton dans le code Java de la classe ci-dessous. toutes les classes sont isolées, séparées, et rendues indépendantes.


Ceci est possible grâce à la présence des JARs Spring dans la classpath, ensembles(les JARs) avec la classe SpringLauncher.java qui cherche le fichier de configuration Spring app-context.xml qui définie comme suite :




Après les six premières lignes, qui sont l'en-tête de notre fichier de configuration, voici la description détaillée de chaque élément:


Lignes 8-15: définisses la classe MyJFrame, en spécifiant sa propriété"title" et sa propriété "contentPane". Notez la définition de l'attribut "init-method", dont la valeur est le nom la méthode "init" de la classe MyJFrame que nous utiliserons pour l'instanciation de la classe.


Lignes 17-26 Définisse le mainPanel, qui va contenir deux JTextField et une autre instance de lui nommée buttonPanel, définie dans les lignes 28-35. Nous fixons aussi la propriété nommée "axis" et  la propriété nommée "panelComponents". Les deux panels sont construits à partir de la classe JPanel. Le premier d'entre eux est utilisé afin de définir sa propriété "axis" du layout utilisé par la classes MyJPanel qui un BoxLayout. En revanche la propriété "panelComponents" va être remplié par nos trois composant Swing à savoir les deux JTextField et le buttonPanel. Un iterator dans la classe MyJPanel va bouclé autour des composant reçu, en les y ajoutant. Tout ça aura lieu dans la méthode "init", qui est définie comme valeur de l'attribut "init-method".


Lignes 28-35: Définisses le panel du bas qui contient seulement la classes MyJButton. Notez que ce panel est définit par la même classes définissant le mainPanel. Donc nous réutilisons la classe MyJPanel par le biais du fichier de configuration Spring.


Ligne 37Définie le premier JTextField.
Ligne 38: Définie le deuxième JTextField.


Lignes 40-47: Définisses  le JButton, avec ses deux propriétés  "text" et "actionListener". Notez que nous n'avons pas définit les propriétés "text" des JTextFields que nous pouvons le faire. Vous pouvez définir la propriété "text" et les autres dans le fichier de configuration Spring,le choix est le votre.


Ligne 49: Définie l'ActionListener.


Voici le fichier de configuration complet qui est facile à lire, pas de grandes surprises. Maintenant voyant à quoi ces classes ressembles exactement. Le code source de la classe MyJFrame a été montrer ci-haut. voici le code source des autres classes :



package springSwinging;
import java.awt.Component;
import java.util.Iterator;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
/**
 *
 * @author Arafat Bouchafra
 * @Date   2 déc. 2010
 * @Time   03:09:26
 */
public class MyJPanel extends JPanel {
    private List panelComponents;
    private int axis;
    public void setAxis(int axis) {
        this.axis = axis;
    }


    public void setPanelComponents(List panelComponents) {
        this.panelComponents = panelComponents;
    }


    public void init() {
        setLayout(new BoxLayout(this, axis));
        for (Iterator iter = panelComponents.iterator(); iter.hasNext();) {
            Component component = (Component) iter.next();
            add(component);
        }
    }
}

package springSwinging;
import javax.swing.JTextField;
/**
 *
 * @author Arafat Bouchafra
 * @Date   2 déc. 2010
 * @Time   03:10:58
 */
public class MyJTextField extends JTextField {
    public void init() {
        setText("hello world");
    }
}

package springSwinging;
import java.awt.event.ActionListener;
import javax.swing.JButton;
/**
 *
 * @author Arafat Bouchafra
 * @Date   2 déc. 2010
 * @Time   03:11:32
 */
public class MyJButton extends JButton {
    private ActionListener actionListener;
    public void setActionListener(ActionListener actionListener) {
        this.actionListener = actionListener;
    }

    public void init() {
        this.addActionListener(actionListener);
    }
}

package springSwinging;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JOptionPane;
/**
 *
 * @author Arafat Bouchafra
 * @Date   2 déc. 2010
 * @Time   03:12:22
 */
public class MyActionListener implements ActionListener {

    public void actionPerformed(ActionEvent e) {
        JOptionPane.showMessageDialog(null, "Hello from Spring!");
    }
}

Nous avons ajouté un ActionListener à MyJButton, mais nous n'avons pas spécifié lequel. Pour changer l'ActionListener, modifiez seulement la ligne 49 du fichier de configuration Spring. Changez seulement l'attribut "classname" vers un autre ActionListener que vous devez définir. Clairement, il n'y a pas de code Java connectant la classe "MyActionListener" à la classe "MyJButton". Similairement, il n'y a pas de code Java connectant les composants Swing entre eux. De point de vue utilisateur final, il n'y a pas de difference. Mais de point de vue développeur, toutes les connexions entres les composants seront faites dans le fichier de configuration Spring, et voir même entre composants et leurs actions (MyJButton et MyActionListener) .

Finalement, jetons un coup d'oeil sur la classe SpringLauncher.java, qui utilise un code spécifique à Spring:

package springSwinging;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 *
 * @author Arafat Bouchafra
 * @Date   2 déc. 2010
 * @Time   03:12:59
 */
public class SpringLauncher {

    public static void main(String[] args) {
        String[] contextPaths = new String[]{"app-context.xml"};
        new ClassPathXmlApplicationContext(contextPaths);
    }
}

Maintenant, que est ce nous avons gagné? Est ce que Spring encourage vraiment une désintégration des composants Swing à ce bas niveau? Pas nécessairement , mais possible. Le point est, vous pouvez détacher autant que vous voulez. Tout dans la même application. Mais pourqoui faire ça ? Maintenant que nous avons compris le QUOI, allons voire le POURQUOI. Il y a pas mal de livre traitant le POURQUOI. le POURQUOI est "dependency injection [1]"(l'injection de dépendences) et "loose coupling" (Accouplement desserré(libre)). Un bon avantage est celui là, Parce que vos composants sont vraiment séparés l'un de l'autre,il est facile de les tester. Vos tests de JUNIT (ou d'autres tests) seront plus faciles à écrire parce qu'il n'y a aucune gêne d'une classe à une autre. Aussi, en ce qui concerne le code de plomberie, c'est-à-dire, le câblage(le wiring), que deviez-vous normalement maintenir(entretenir)? Tout cela est maintenu dans le fichier de configuration Spring; Aucun de cela n'est dans le code Java. Notez aussi que le fichier de configuration Spring est non-envahissant. Vous pouvez simplement le glisser dans une application existante, Écrivez un bean pour la classe principale et ajoutez ensuite le code du lanceur. Alors vous êtes bon pour  y aller. Ainsi, l'intégration avec vos applications Swing existantes peut arriver sans vous ayant besoin de changer ces classes existantes, à moins que vous ne vouliez faire, ça c'est une autre chose.

Finalement, regardant de nouveau notre JPanel. C'est un composant Swing réutilisable (comme les autres composants Swing utilisés ici, comme le JTextField, que vous avez réutilisé aussi). Vous l'avez utilisé deux fois dans la même application, pour des buts différents. A chaque fois, vous avez beaucoup de composant sur le layout du JPanel, depuis le fichier de configuration Spring, bien que vous utilisiez le même JPanel, son contenu pourrait être différent chaque fois vous le réutilisez. Encore, notez l'utilisation de la liste générique d'objets ici. Au lieu de spécifier un composant Swing particulier, qui aurait fait le JPanel moins réutilisable, nous avons opté pour une liste générique d'objets pour que nous ne serons pas limités par les composants qu'elle peut manipulée. Ce qu'il faut prendre en considération en créant des composants Swing détachés est, en travaillant d'une façon détachée a un impact sur votre processus de design.

J'espère que cela sert d'une introduction utile à Spring Framework dans le contexte de Swing.

Dans le prochain tutoriel, Nous allons utilisé un autre Framework de IoC, cette fois ci, il s'agit de Google Guice, nous allons introduire le principe de module.

N'hésitez pas à nous écrire, faire vos remarque ;-)