Précédent   Forum du club des développeurs et IT Pro > Java > Général Java > Persistance
Persistance Forum d'entraide pour la persistance en Java : base de donnée, xml, mapping orienté objet, ... Posez vos questions sur iBatis, JDO, XmlBeans, Castor, JAXB, XStream, ...
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 05/10/2012, 16h16   #1
SuperArbre
Membre à l'essai
 
Homme
graphisme & impression
Inscription : mars 2011
Messages : 72
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Suisse

Informations professionnelles :
Activité : graphisme & impression

Informations forums :
Inscription : mars 2011
Messages : 72
Points : 24
Points : 24
Par défaut "nullPointer exception", je trouve pas l'erreur

Bonjour,

Je suis entrain de faire ma première application en Java et j'ai une erreur que je ne comprends pas! Enfin j'ai compris que l'objet était null quelque part mais je comprends pas où!

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at servicescrud.AccesBDD.newTransaction(AccesBDD.java:58)
at servicesFonctionnels.ServicesFonctionnelsPatient.memoriser(ServicesFonctionnelsPatient.java:15)
at controler.ControlerPatient.controle(ControlerPatient.java:18)

L'application est composé comme ça:
Vue
Controler
Modele (avec les services d'appel à la base de données)
Singelton AccesBDD pour l'entityManager.


Je suis débutant donc désolé si quelque chose vous parait pas très pro.
Merci beaucoup pour votre aide.
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
 
package controler;
 
import toolbox.Message;
import entites.Patient;
import model.Model;
 
public class ControlerPatient extends AbstractControler{
 
 
	public ControlerPatient(Model pModel){
		super(pModel);
	}
 
 
	public Boolean controle(Patient pPatient) {
		Boolean controle = false;
		if(pPatient.getPrenom() != null){
			this.model.getSfPatient().memoriser(pPatient);
			System.out.println(Message.getStatut());
		}
		return controle;
	}
 
 
 
}
 
package model;
 
import java.util.Date;
 
import servicesFonctionnels.IServicesFonctionnels;
import servicesFonctionnels.ServicesFonctionnelsConsultation;
import servicesFonctionnels.ServicesFonctionnelsPatient;
 
import entites.Consultation;
import entites.Therapeute;
 
public class Model extends AbstractModel{
 
 
	private ServicesFonctionnelsPatient sfPatient;
 
	public Model(){
		super();
		this.sfPatient = new ServicesFonctionnelsPatient();
	}
 
	public ServicesFonctionnelsPatient getSfPatient() {
		return sfPatient;
	}
 
	public void setSfPatient(ServicesFonctionnelsPatient sfPatient) {
		this.sfPatient = sfPatient;
	}
 
 
 
 
}
 
package servicesFonctionnels;
 
 
import servicescrud.AccesBDD;
import servicesunitaires.ServicesUnitairesPatient;
import toolbox.Message;
import entites.Patient;
 
public class ServicesFonctionnelsPatient implements IServicesFonctionnels<Patient>{
 
	private static ServicesUnitairesPatient suPatient = new ServicesUnitairesPatient();
	private static AccesBDD singelton = AccesBDD.getInstance();
 
	public void memoriser(Patient pPatient) {
		singelton.newTransaction();
		suPatient.creer(pPatient);
		Message.setStatut(Message.TypeStatut.objetMemorise);
		singelton.endTransaction();
	}
 
	public Patient editer(Patient pPatient) {
		singelton.newTransaction();
		Patient patientRecherche = suPatient.valider(pPatient);
		if(Message.getStatut() == Message.TypeStatut.objetValide){
			Message.setStatut(Message.TypeStatut.objetEdite);
		}
		singelton.endTransaction();
		return patientRecherche;
	}
 
	public void modifier(Patient pPatient) {
		singelton.newTransaction();
		if(Message.getStatut() == Message.TypeStatut.objetEdite){
			suPatient.mettreAjour(pPatient);
			Message.setStatut(Message.TypeStatut.objetModifie);
		}
		singelton.endTransaction();
	}
 
	public void efface(Patient pPatient) {
		singelton.newTransaction();
		Patient patientRecherche = suPatient.valider(pPatient);
		if(Message.getStatut() == Message.TypeStatut.objetValide){
			suPatient.supprimer(patientRecherche);
			Message.setStatut(Message.TypeStatut.objetEfface);
		}
		singelton.endTransaction();
	}
 
 
 
}
 
 
package servicescrud;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
 
public class AccesBDD {
 
	public static final String NOM_UNIT = "jpa";
 
	private static AccesBDD singleton = null;
 
	private EntityManagerFactory emf;
 
	private EntityManager em;
 
	private EntityTransaction transaction;
 
	private AccesBDD(){
		try{
			this.emf = Persistence.createEntityManagerFactory(NOM_UNIT);
			this.em = emf.createEntityManager();
		} catch (Exception e) {
			throw new RuntimeException("Connexion impossible... Verifier le serveur de BDD et le fichier persistence.xml up :"+NOM_UNIT+e.getMessage());
		}
	}
 
	public static AccesBDD getInstance() {
		if (singleton == null){
			singleton = new AccesBDD();
		}
		return singleton;
	}
 
	public EntityManager getEntityManager(){
		return this.em;
	}
 
 
	public void deconnecte() throws Exception{
		if (emf != null){
			emf.close();
			emf = null;
		}
		if (em != null){
			em.close(); 
			em = null;
		}
	}
 
 
	public void endTransaction() {
		this.transaction.commit();
	}
 
	public void newTransaction() {
		this.transaction = this.em.getTransaction();
		this.transaction.begin();
	}
 
}
SuperArbre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/10/2012, 17h27   #2
andry.aime
Rédacteur/Modérateur
 
Avatar de andry.aime
 
Homme Andry Aimé
Inscription : septembre 2007
Messages : 6 368
Détails du profil
Informations personnelles :
Nom : Homme Andry Aimé
Localisation : Ile Maurice

Informations forums :
Inscription : septembre 2007
Messages : 6 368
Points : 9 989
Points : 9 989
Bonsoir,

Tu as un NullPointerException, c'est que tu utilises un variable non instancié (avec un new ou par injection) à la ligne 58 de la classe AccesBDD.java.

Peut-on voir le code de cette classe?

A+.
andry.aime est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/10/2012, 18h47   #3
SuperArbre
Membre à l'essai
 
Homme
graphisme & impression
Inscription : mars 2011
Messages : 72
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Suisse

Informations professionnelles :
Activité : graphisme & impression

Informations forums :
Inscription : mars 2011
Messages : 72
Points : 24
Points : 24
Par défaut merci

Coucou,

Merci pour ta réponse… J'ai compris qu'il s'agit d'une variable non-instancié*…
En fait, je suppose que mon problème vient de la class AccesBDD mais je comprends pas pourquoi… Mon but c'est de faire un singelton avec cet class car l'entity manager doit être déclarer une seule fois d'après ce que j'ai compris…

Par contre je comprends pas pourquoi il est null car je l'appel toujours via getInstance qui initialise les deux variables*…

Merci beaucoup pour votre aide

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
 
 
package servicescrud;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
 
public class AccesBDD {
 
	public static final String NOM_UNIT = "jpa";
 
	private static AccesBDD singleton = null;
 
	private EntityManagerFactory emf;
 
	private EntityManager em;
 
	private EntityTransaction transaction;
 
	private AccesBDD(){
		try{
			this.emf = Persistence.createEntityManagerFactory(NOM_UNIT);
			this.em = emf.createEntityManager();
		} catch (Exception e) {
			throw new RuntimeException("Connexion impossible... Verifier le serveur de BDD et le fichier persistence.xml up :"+NOM_UNIT+e.getMessage());
		}
	}
 
	public static AccesBDD getInstance() {
		if (singleton == null){
			singleton = new AccesBDD();
		}
		return singleton;
	}
 
	public EntityManager getEntityManager(){
		return this.em;
	}
 
 
	public void deconnecte() throws Exception{
		if (emf != null){
			emf.close();
			emf = null;
		}
		if (em != null){
			em.close(); 
			em = null;
		}
	}
 
 
	public void endTransaction() {
		this.transaction.commit();
	}
 
	public void newTransaction() {
		this.transaction = this.em.getTransaction();
		this.transaction.begin();
	}
 
}
SuperArbre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/10/2012, 14h10   #4
SuperArbre
Membre à l'essai
 
Homme
graphisme & impression
Inscription : mars 2011
Messages : 72
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Suisse

Informations professionnelles :
Activité : graphisme & impression

Informations forums :
Inscription : mars 2011
Messages : 72
Points : 24
Points : 24
Par défaut une idée

Bonjour,

Personne n'a une idée? Je comprends pas ma faute car pour moi le singleton garanti que mon instance n'est pas null…

Merci
SuperArbre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/10/2012, 18h10   #5
djanggawul
Candidat au titre de Membre du Club
 
Inscription : novembre 2006
Messages : 37
Détails du profil
Informations forums :
Inscription : novembre 2006
Messages : 37
Points : 13
Points : 13
Bonjour,

L'exception indique que ton objet EntityManager de ta classe AccesBDD est null lors de l'exécution de la méthode newTransaction.

A première vue, il semble que ton singleton soit bien initialisé. Donc ta variable doit être mise à null après la création du singleton. Je vois que ta méthode deconnecte fait cela. Tu dois donc avoir un appel qui est fait à cette méthode.

Tu peux vérifier cela en posant des points d'arrêts en debug.
djanggawul est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/10/2012, 12h22   #6
SuperArbre
Membre à l'essai
 
Homme
graphisme & impression
Inscription : mars 2011
Messages : 72
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Suisse

Informations professionnelles :
Activité : graphisme & impression

Informations forums :
Inscription : mars 2011
Messages : 72
Points : 24
Points : 24
Par défaut merci

Hello,

Merci infiniment, c'était bien cela!
Merci beaucoup, bonne journée
SuperArbre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/10/2012, 14h00   #7
Sebajuste
Candidat au titre de Membre du Club
 
Inscription : février 2006
Messages : 8
Détails du profil
Informations forums :
Inscription : février 2006
Messages : 8
Points : 13
Points : 13
Attention toutefois, le même bug peut survenir à cause de l'environnement mutli-thread induit par l'utilisation d'AWT.

En effet, même si tu n'as pas créer explicitement de threads, ton application est bien et bien multi-threadé.
En atteste l'exception générée: "Exception in thread "AWT-EventQueue-0"
Il s'agit, du thread qui gère les évènements de ton interface graphique.

Or, AccesBDD étant un singleton, ta classe est accessible aussi bien par le thread principal (l'appel à static void main(...) ), qu'au thread d'affichage (méthode paint() et companie) et au thread des évènements de l'interface.

De fait, ta classe doit être thread-safe, ce qui n'est pas le cas.
Et le même problème peut survenir de pointeur null peut survenir !
En effet, ton entityManager est créé à l'instanciation de la classe AccesBDD.

Les problèmes pouvant survenir sont les suivants:
-deux appels à la méthode statique getInstance() peuvent instancier deux fois l'objet (il suffit que les deux threads arrivent à la condition "singleton == null" en même temps).
- l'instance a bien été construire une seule fois, mais les différents threads ne sont pas au courant de la bonne "publication" d'une variable (ex: un thread peut voir em à null, et un autre instancié).
- plusieurs thread tentent de faire des opérations en base de données en même temps (et je ne suis pas sur que les transactions soient thread-safe).



Pour ce qui est de la "publication" d'une variable, il faut comprendre que chaque thread travail avec sa propre mémoire. Celle-ci doit alors être synchronisée avec la mémoire centrale pour "lire" la valeur réelle de certaines variables, ou pour "écrire". Sans celà, on peut lire des valeurs obsolète, ou encore écrire une valeur qui ne sera jamais mise à jour.
La synchronisation ne peut être "forcée" que par des block synchronized, ou par l'appel de méthode lock() et unlock() d'un objet implémentant l'interface Lock.

(Je prends beaucoup de raccourcis, le sujet est vase, je te laisses juste quelques pistes pour faire des recherches plus approfondies).


Le problème peut être le suivant:
Ton instance a été initialisé dans le thread principal, celui-ci possède toutes les variables "à jour".
Le thread d'évènement récupère l'instance, mais pour lui, les attributs sont toujours à null, car la synchronisation de la mémoire n'a pas été faite. Tu as donc un pointeur null. Alors que ce n'est normalement le cas, EntityManager a bien été crée, mais le thread d'évènement n'est tout simpelment pas au courant...





Pour solutionner ton problème, il te faut en premier remédier à la bonne initialisation du singleton.


private static final AccesBDD singleton = new AccesBDD();

voir: http://christophej.developpez.com/tu...n/multithread/



Tu peux remarquer l'ajout du mot clef "final". Celui ci interdit la réaffectation de la variable. Ca a son intérêt dans un environnement multi-thread, puisque celà permet à la JVM de faire des optimisations sur son modèle mémoire.

En effet, la variable ne pouvant pas prendre d'autres valeurs, on s'assure de sa bonne publication, et donc de sa bonne visibilité par les autres threads. Il n'est pas nécéssaire dans ce cas de faire de synchronisation.

Pour résumer:
- soit tu utilises le mot clef "final" sur un attribut
- soit il faut synchroniser l'affectation de l'attribut pour s'assurer de sa bonne visibilité aux autres threads.



Il reste le fait de t'assurer que deux threads ne puissent pas exécuter de transaction en même temps. Ce que permet ta classe en l'état actuel.
Sebajuste est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 20h39.


 
 
 
 
Partenaires

Hébergement Web