Bonjour (ou Bonsoir)

JBoss n'est pas content quand j'appelle la méthode test1() de mon bean SessionTests :

21:02:47,474 ERROR [org.jboss.as.ejb3.invocation] (http-/127.0.0.1:8080-1) JBAS014134: L'invocation EJB a échoué sur le composant SessionTests pour la méthode public abstract java.lang.String org.gfarny.ejb3.SessionTestsRemote.test1() throws java.text.ParseException: javax.ejb.EJBException: javax.persistence.EntityExistsException: a different object with the same identifier value was already associated with the session: [org.gfarny.ejb3.EntityBudyPhone#EntityBudyPhone[0,0]]

"...with the same identifier value..." : voilà le problème.



Bean de la méthode test1() censée faire une instantiation frauduleuse :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
package org.gfarny.ejb3;
 
import java.text.ParseException;
import java.text.SimpleDateFormat;
 
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.PostActivate;
import javax.ejb.PrePassivate;
import javax.ejb.Remote;
import javax.ejb.Stateful;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
 
@Stateful
@Remote(SessionTestsRemote.class)
public class SessionTests implements SessionTestsRemote {
	private static EntityManagerFactory emf;
	private static EntityManager em;
 
	public SessionTests () {}
 
	@Override
	public EntityManager getEntityManager() {
		return em;
	}
 
	@Override
	public String test1 () throws ParseException {
		StringBuffer buf = new StringBuffer();
		EntityTransaction tx = em.getTransaction();
		tx.begin();
 
		EntityBudy b1 = new EntityBudy(
					"Martin", "Paul", new SimpleDateFormat("dd/MM/yy").parse("31/01/2000"));
		EntityBudy b2 = new EntityBudy(
				"Jacqueline", "Duchemin", new SimpleDateFormat("dd/MM/yy").parse("12/02/1980"));
		EntityPhone p1 = new EntityPhone("0654512961");
		EntityBudyPhone bp1 = new EntityBudyPhone(b1,p1);
		EntityBudyPhone bp2 = new EntityBudyPhone(b2,p1);
		//b1.addEntityBudyPhone(p1);
		//p1.addEntityBudyPhone(b2);
		em.persist(b1);
		em.persist(b2);
		em.persist(p1);
		em.persist(bp1);
		em.persist(bp2);
 
		tx.commit();
 
		// test purpose
		for (Object c : em.createQuery("select c from EntityCountry c order by c.code asc").getResultList()) {
			buf.append(((EntityCountry)c).getCode());
			buf.append(", ");
		}
 
		tx = null;
		return buf.toString();
	}
 
	@PostConstruct
    public void postConstruct()
    {
		// "jpa" fait reference au <persistence-unit> du fichier persistence.xml
		emf = Persistence.createEntityManagerFactory("jpa");
		em = emf.createEntityManager();
    }
 
	@PreDestroy
    public void preDestroy()
    {
		em.close();
		emf.close();
    }
 
	@PostActivate
    public void postActivate() {}
 
	@PrePassivate
    public void prePassivate() {}
}
Voici le code JSP qui appelle tout ça :
Code jsp : Sélectionner tout - Visualiser dans une fenêtre à part
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
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"
    import="java.util.*,javax.ejb.*,javax.rmi.PortableRemoteObject,javax.naming.*,org.gfarny.ejb3.*"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<% 
SessionTestsRemote sessionTestsRemote = null;
String c_code = request.getParameter("code");
String c_fullname = request.getParameter("fullname");
try {
        // JBoss 6 specific
    final Hashtable<String, String> jndiProperties = new Hashtable<String, String>();
    jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
        
        InitialContext ctx = new InitialContext(jndiProperties);
        
        // initialise le contexte de Tests : ?stateful useless ???
        sessionTestsRemote = (SessionTestsRemote) ctx.lookup(
                "java:jboss/exported/ejbjpa/ejbjpa.jar/SessionTests!org.gfarny.ejb3.SessionTestsRemote");
        
        // effectue le test1
        sessionTestsRemote.test1();
        
        } catch (Exception e) {
        e.printStackTrace ();
}
 
//...
%>
<br>
<%
// ...
%>
</body>
</html>

...une dernière interrogation :
mon URI JNDI devrait se terminer par "?stateful" quand je fais un lookup, puisque mon bean est stateful,
et que la doc de JBoss précise bien qu'il faut le faire... or dans la liste de mes noms JNDI l'URI apparaît être sans "?stateful"

une idée ?

Merci d'avance !