tp injection

Programmation Avancée

Modérateur : Douin

Répondre
gautierd
Messages : 49
Inscription : 12 oct. 2016 14:55

tp injection

Message par gautierd » 14 janv. 2017 12:42

Bonjour à tous,
Je suis bloqué sur un point.
Lorsque l'on récupère du fichier de conf une certaine valeur, elle est récupérée en string.
Ce que l'on veut, c'est invoquer une méthode avec cette valeur du style
m.invoque(InstanceAppliquée, Paramètre)
Mais ce paramètre varie. Alors comment faire le lien Paramètre/ValeurString ?
Si je lis un int (4 pour la taille de liste), comment faire pour que paramètre soit déterminé int ?
J'espère que c'est assez clair. Merci.

tasic
Messages : 28
Inscription : 09 oct. 2016 14:13

Re: tp injection

Message par tasic » 14 janv. 2017 14:22

Je bloque sur ce point aussi.

Je vais tester avec ça et te tiens au courant

Code : Tout sélectionner

for (Class<?> p : m.getParameterTypes() ) {
    String parameterString = p.getName();
    System.out.println("parameterString   " + parameterString);
} 
En gros l'idée
On construit notre String setter (setTable)
On vérifie qu'il existe bien
On récupère son type (le bout de code plus haut)
En fonction de son type on cast comme il faut avec un Enum

Je me demande si il n'y a pas plus simple mais sur le papier ça devrait marcher...
A suivre

tasic
Messages : 28
Inscription : 09 oct. 2016 14:13

Re: tp injection

Message par tasic » 14 janv. 2017 15:55

Bon rien ne marche comme je voudrais je n'arrive pas à caster comme il faut...

NAVARRO
Messages : 30
Inscription : 02 oct. 2016 13:44

Re: tp injection

Message par NAVARRO » 14 janv. 2017 16:18

J'en suis encore à l'étape avant ça... comment lire le fichier de config etc..

Si j'ai compris le TP:

1)Choisir son implémentation parmi les 4 possibles : Properties avec FileSystemPropsApplicationContext , XML, JSON ou Text
2) Parser le fichier et alimenter la Map "beans" avec un string et une instance de l'objet. Dans cet étape il faut donc créer une instance de l'objet et utilise le setter pour initialiser l'objet avec les autres parametres du fichier de config:

public abstract class AbstractApplicationContext implements ApplicationContext, Iterable<String>{
protected Map<String, Object> beans;

Si je prends l'exemple du message le plus simple:
bean.id.8=message
message.class=question1.Message
message.property.1=message
message.property.1.param.1=Cnam femtoContainer is fun

Le cas de test ==> ctx.getBean nous retourne donc une instance de la classe Message

public void testMessage()throws Exception{
// inspiré de :
// http://www.springbyexample.org/static/1 ... ation.html
ApplicationContext ctx = Factory.createApplicationContext();
Message message = (Message) ctx.getBean("message");
assertEquals("Cnam femtoContainer is fun", message.getMessage());

public class Message{
private String message;

public void setMessage(String message){
this.message = message;
}

public String getMessage(){
return this.message;
}
}

als
Messages : 10
Inscription : 29 déc. 2016 19:02

Re: tp injection

Message par als » 14 janv. 2017 17:35

Bonjour gaultier, tasic,

Il faudra utiliser la réflexion. Etant donné qu'on applique l'injection par la technique des setters, on se retrouvera dans 2 cas:

- soit le paramètre fait référence à un autre bean. On recherchera donc, dans ce cas, le bean dans notre map et l'utiliser en paramètre dans la méthode setter.
- soit ce n'est pas une référence à un autre bean. On cherche donc par réflexion le type que prend notre méthode setter en paramètre, (reflexion "Method - getParameterTypes),
puis on "parse" la chaine de caractère, de notre fichier de paramètre, vers le type en question.

Pour ton exemple gaultier ("4" en paramètre): ce sera donc 'Integer.parseInt("4")', car l'appel getParameterType de la méthode setter nous aura retourné un int.class.

gautierd
Messages : 49
Inscription : 12 oct. 2016 14:55

Re: tp injection

Message par gautierd » 14 janv. 2017 21:39

Merci pour les retours mais j'y arrive toujours pas.

Je me suis quand même inspiré de ce que tu m'as dit als.

J'ai écrit du coup que pour chaque bean, je parcours les propriétés et alors :

// si l'element est une propriete du bean
if(key.matches("^" + beanName + "\\.property\\." + "([0-9]+)$")) {
// on recupere le parametre de cette propriete
String param = props.getProperty(key + ".param.1");
Class c = Class.forName("question1." + beanName);
// si le parametre est un bean
if(beans.containsKey(param)) {
for(Method m : c.getMethods()) {
if(m.getName().toLowerCase().equals("set"+value)) {
m.invoke(beans.get(beanName), beans.get(param));
}
}
}
// le parametre est une valeur brute que l'on doit appliquer
else {
System.out.println(key+"="+value);
for(Method m : c.getMethods()) {
if(m.getName().toLowerCase().equals("set"+value)) {
Class<?>[] p = m.getParameterTypes();
System.out.println("INVOQUE " + m.getName() + "bean:"+beanName);
if (p[0] == int.class)
{
m.invoke(beans.get(beanName),Integer.parseInt(param));
}
if (p[0] == String.class)
{
System.out.println("INVOQUE MESSAGE " + value);
m.invoke(beans.get(beanName), param);
}
}
}
}
}

Mais du coup, çà marche pas. Les beans doivent bien être sauvegardés avant. Mais l'appel des setters ne fonctionnent pas. Est ce que quelqu'un peut m'aider ?

NAVARRO
Messages : 30
Inscription : 02 oct. 2016 13:44

Re: tp injection

Message par NAVARRO » 15 janv. 2017 1:51

Je suis maintenant arrivé au même point que vous et je bloque aussi sur le type des paramètres de la méthode à utiliser

Exemple:

Récapitulatif des Bean détectés:

id=bean.id.9, type=properties, classe=question1.PropertiesType
properties.property.7=bool, properties.property.7.param.1=true
properties.property.6=d, properties.property.6.param.1=1.0
properties.property.5=f, properties.property.5.param.1=1.0
properties.property.4=l, properties.property.4.param.1=1
properties.property.3=i, properties.property.3.param.1=1
properties.property.2=s, properties.property.2.param.1=1
properties.property.1=b, properties.property.1.param.1=1

classe = question1.PropertiesType
canonical name de la classe = question1.PropertiesType
classe = question1.PropertiesType
classe de l'objet o = question1.PropertiesType
PremiereLettre de la méthode = B
nom de la méthode = setBool
Propriété = bool, parametre = true

Une méthode de question1.PropertiesType : setB
Une méthode de question1.PropertiesType : setB
Une méthode de question1.PropertiesType : setI
Une méthode de question1.PropertiesType : setI
Une méthode de question1.PropertiesType : setS
Une méthode de question1.PropertiesType : setS
Une méthode de question1.PropertiesType : setL
Une méthode de question1.PropertiesType : setL
Une méthode de question1.PropertiesType : setF
Une méthode de question1.PropertiesType : setF
Une méthode de question1.PropertiesType : setD
Une méthode de question1.PropertiesType : setD

Methode trouvée : setBool

Methode trouvée : setBool
Une méthode de question1.PropertiesType : calcul
Une méthode de question1.PropertiesType : wait
Une méthode de question1.PropertiesType : wait
Une méthode de question1.PropertiesType : wait
Une méthode de question1.PropertiesType : equals
Une méthode de question1.PropertiesType : toString
Une méthode de question1.PropertiesType : hashCode
Une méthode de question1.PropertiesType : getClass
Une méthode de question1.PropertiesType : notify
Une méthode de question1.PropertiesType : notifyAll

Méthode = setBool
nombre de parametres : = 1
type du parametre : java.lang.Boolean

Je me dis donc que j'ai un paramètre "true" qui est un String , mais que ma méthode setBool veut un Boolean ou un boolean d'ailleurs!

Faut - il donc aussi chercher la liste des constructeurs possibles?? et ensuite , dans ce cas présent je devrais utilise le 2eme qui prend un String en argument...

Boolean(boolean value)
Allocates a Boolean object representing the value argument.
Boolean(String s)
Allocates a Boolean object representing the value true if the string argument is not null and is equal, ignoring case, to the string "true".

En résumé, cela devient compliqué , car plusieurs cas vont être possibles mais depuis le début , voici ce que j'ai fait dans le but uniquement d'initialiser le HashMap beans de AbstractApplicationContext !

on liste le fichier de configuration , on recherche la classe
exemple bean.id.9=properties et properties.class=question1.PropertiesType

on créé une instance de cette classe pour l'ajouter en tant qu'objet dans la HashMap.
pour pouvoir l'initialiser correctement on doit appeler une de ses méthodes , mais on ne connait pas son nom , ni son parametre, ni le type de ce parametre. (on suppose qu'il n'y a qu'un seul parametre mais il pourrait y en avoir plusieurs?!!)

Dans le cas de mon exemple , je suis en plus tombé sur 2 méthodes pour ma propriété, comment déterminer laquelle utiliser?

il faut créer une instance de cette classe paramètre si nécessaire(puisque ma méthode setBool veut un Boolean ou boolean et pas un string ) et utiliser le bon constructeur ...

voila ou j'en suis. Cela devient très compliqué je trouve :)

NAVARRO
Messages : 30
Inscription : 02 oct. 2016 13:44

Re: tp injection

Message par NAVARRO » 15 janv. 2017 2:07

Des méthodes de la classe Class intéressantes peut être :

T cast(Object obj)
Casts an object to the class or interface represented by this Class object.

boolean isInstance(Object obj)
Determines if the specified Object is assignment-compatible with the object represented by this Class.

boolean isPrimitive()
Determines if the specified Class object represents a primitive type.

J'ai aussi relu les diapos 28 à 40 du cours 7.

Gouesmel
Messages : 1
Inscription : 15 janv. 2017 12:01

Re: tp injection

Message par Gouesmel » 15 janv. 2017 12:04

Bonjour

Ca me rassure de voir tous ces message, ce tp est vraiment pas évident
Après pas mal de temps passé sur ce tp, j'ai réussi à passer les tests présents dans la classe "ApplicationContextTests"!

Mais quand je tente de soumettre à JNews, j'échoue à tous les tests... Je comprends rien !

als
Messages : 10
Inscription : 29 déc. 2016 19:02

Re: tp injection

Message par als » 15 janv. 2017 16:56

Bonjour,

Oui gaultier,
il faudra donc séparer les traitements en deux parties.
- La première qui cherche tous les instances de bean à créer et qui les stocke dans le Map. (Sans affecter les paramètres).
- La deuxieme qui ensuite les reprends à nouveau, et affecte les paramètres. (Car un paramètre peut être une référence à un autre bean, donc il aura fallu instancier tous les beans dans un premier temps).

Ensuite, pour invoker les setters, ce sera donc soit :
- l'argument est un autre bean. Donc : maMethodeSetter.invoke(monBean, new Object[]{ leTypeDuBeanArgument.cast(monBeanEnArgument) } );
- l'argument est un type primitif. Donc : maMethodeSetter.invoke(monBean, new Object[]{ XXX.parseXXX(monArgumentEnString) } );
où XXX est mon type primitif. Pour ton dernier exemple en Int, on se retrouve donc avec : Integer.parseInt(monArgumentEnString).

Dans le 2ème cas, on aura donc forcément un bon nombre de cas, ce serait donc mieux de passer par une méthode dédiée, qui nous retournera notre tableau d'Object.

Douin
Messages : 218
Inscription : 18 mars 2009 15:46

Re: tp injection

Message par Douin » 16 janv. 2017 11:26

Bonjour,

Je partage vos réponses,

Le nom de la méthode associée au "setter" est par convention setAttribut (cf diapositive 35 de http://jfod.cnam.fr/NFP121/supports/NFP ... ection.pdf)

le type de l'attribut peut être obtenu par getDeclaredField, et cet attribut peut être déclaré dans une super classe, c'est le cas dans l'exemple de la chaine de responsabiltés cf http://deptmedia.cnam.fr/phpBB2/viewtop ... d2ee783aa3

L'attribut peut aussi ne pas être déclaré ... c'est la cas de l'exemple de l'IHM (cf. la classe de tests unitaires)

Bonne fin de tp

dès mercredi matin je mettrai une solution en ligne, vous pourrez si vous le souhaitez contribuer à la base d'exemples

Douin
Messages : 218
Inscription : 18 mars 2009 15:46

Re: tp injection

Message par Douin » 18 janv. 2017 12:41

Bonjour,

Une solution est en ligne, elle est perfectible,

http://lmi92.cnam.fr/progAvancee/source ... le_des_TP/


Bonne lecture

Douin
Messages : 218
Inscription : 18 mars 2009 15:46

Re: tp injection

Message par Douin » 25 janv. 2017 12:35

Bonjour,

Une nouvelle version est en ligne, elle est, elle aussi, perfectible,

http://lmi92.cnam.fr/progAvancee/source ... le_des_TP/


Bonne lecture

Répondre

Qui est en ligne ?

Utilisateurs parcourant ce forum : Aucun utilisateur inscrit et 1 invité