Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipselink-users] (Long) Oddities using EclipseLink 2, NetBeans 6.8, EJB and GlassFish 3.0

I'm not sure what you intend to happen, also perhaps include an SQL trace.

You test code looks a little odd.  The main issue with it is that the client
Id is a generated Id and never passed back to the test client, so will
remain null.  This will trigger your delete to first merge a new client,
then try to delete this new client.


RogerV wrote:
> 
> Hi
> 
> This is my first foray into the field of EJB and JPA persistence using 
> EclipseLink 2.0. Given my knowledge of these areas I've no idea where the 
> problem lies and I hope that someone can point me in the right direction.
> 
> I've created enities, CLient and Phone (an abstract class) with  a bi-
> directional @ManyToOne between them, and MobilePhone as a concrete entity 
> class. I've used the NetBeans code generation tool to create the
> ClientFacade 
> and PhoneFacade stateless session beans that actually perform the CRUD 
> operation. I've then created a ClientService  stateless session bean that
> will 
> contain the business logic that controls the CRUD operations. Lastly, I
> have 
> my ClientServiceTest class that contains my unit tests.
> 
> 
> package com.vasilikon.processes;
> 
> import com.vasilikon.entity.Client;
> import com.vasilikon.entity.Example;
> import com.vasilikon.entity.MobilePhone;
> import com.vasilikon.exceptions.PhoneNumberException;
> import javax.ejb.SessionContext;
> import javax.ejb.embeddable.EJBContainer;
> import org.junit.After;
> import org.junit.AfterClass;
> import org.junit.Before;
> import org.junit.BeforeClass;
> import org.junit.Test;
> import static org.junit.Assert.*;
> 
> /**
>  *
>  * @author varleyr
>  */
> public class ClientServiceTest {
> 
>     static EJBContainer ejbc;
>    
> 
>     public ClientServiceTest() {
>     }
> 
> 
> 
>     @BeforeClass
>     public static void setUpClass() throws Exception {
>     ejbc = EJBContainer.createEJBContainer();
> 
>     }
> 
>     @AfterClass
>     public static void tearDownClass() throws Exception {
>     ejbc.close();
>     }
> 
>     @Before
>     public void setUp() {
>     }
> 
>     @After
>     public void tearDown() {
>     }
> 
>     /**
>      * Test of create method, of class ExampleService.
>      */
>     @Test
>     public void testCreate() throws Exception {
>         System.out.println("create");
> 
>         Client client = new Client();
>         client.setFirstName("Roger");
> 
>         MobilePhone mobile = new MobilePhone(99887766);
>         mobile.setClient(client);
> 
>         client.getPhones().add(mobile);
> 
>         ClientService instance = (ClientService) 
> ejbc.getContext().lookup("java:global/classes/ClientService");
>         instance.create(client);
>         assertTrue(client.getId() != null);
>         instance.delete(client);
>     }
> 
>     @Test
>     public void testCreateDuplicatePhoneNumber() throws Exception {
>         System.out.println("create");
> 
>         Client client = new Client();
>         client.setFirstName("Roger");
> 
>         MobilePhone mobile = new MobilePhone(99887766);
>         mobile.setClient(client);
> 
>         client.getPhones().add(mobile);
> 
>         ClientService instance = (ClientService) 
> ejbc.getContext().lookup("java:global/classes/ClientService");
>         instance.create(client);
>         assertTrue(client.getId() != null);
> 
>         Client dupclient = new Client();
>         client.setFirstName("Fred");
> 
>         MobilePhone dupmobile = new MobilePhone(99887766);
>         mobile.setClient(dupclient);
> 
>         dupclient.getPhones().add(dupmobile);
> 
>         try {
>             instance.create(dupclient);
>             fail();
>         }
>         catch (PhoneNumberException e) {
>         }
>         finally {
>             instance.delete(client);
>         }
> 
>     }
> 
> }
> 
> 
> The first test in the class simply tests for entity creation, and works as 
> expected and the client and phone entities are created with an client id
> of 1 
> and are removed at the end of the test as expected.
> 
> However, the second test testCreateDuplicatePhoneNumber() behaves oddly. 
> Stepping through under debug I see the first entity created and appearing
> in 
> the database as expected with an assigned id of "2".  I also see the entry
> on 
> the phone table associated with customer id 2.  I see the second entity
> class 
> populated correctly with the duplicate phone number and firstName of Fred.
> The 
> code correctly detects the duplicated phone number, does not persist the 
> Client and then deletes the original client from the database. Now when I 
> physically check the database, the Client table contains a row with an id 
> = 3 
> and FirstName = null and the Phone table contains a fully populated record 
> associated with Client_ID = 3.
> 
> And I have no idea why this is happening. I get the same result whether I 
> specify the context.setRollbackOnly() or not. I'm guessing that because I
> see 
> the row in the client table with a firstName value of null when I know
> that 
> the entity instance was initialized to the value "Fred", somehow the Phone 
> entity is being persisted and auto generating the back reference to the
> Client
> 
> Any pointers would be welcome. Source code is below
> 
> Regards
> 
> package com.vasilikon.entity;
> 
> import java.io.Serializable;
> import java.util.ArrayList;
> import java.util.List;
> import javax.persistence.CascadeType;
> import javax.persistence.Entity;
> import javax.persistence.GeneratedValue;
> import javax.persistence.GenerationType;
> import javax.persistence.Id;
> import javax.persistence.OneToMany;
> 
> /**
>  *
>  * @author varleyr
>  */
> @Entity
> public class Client implements Serializable {
>     
>     @Id
>     @GeneratedValue(strategy = GenerationType.IDENTITY)
>     private Long id;
> 
>     private String firstName;
> 
>     @OneToMany(mappedBy = "client", cascade=CascadeType.ALL)
>     private List<Phone> phones;
> 
>     public Client() {
>         this.phones = new ArrayList();
>     }
> 
> 
>     public Long getId() {
>         return id;
>     }
> 
>     public void setId(Long id) {
>         this.id = id;
>     }
> 
>     public String getFirstName() {
>         return firstName;
>     }
> 
>     public void setFirstName(String firstName) {
>         this.firstName = firstName;
>     }
> 
>     public List<Phone> getPhones() {
>         return phones;
>     }
> 
>     public void setPhones(List<Phone> phones) {
>         this.phones = phones;
>     }
> 
>     @Override
>     public int hashCode() {
>         int hash = 0;
>         hash += (id != null ? id.hashCode() : 0);
>         return hash;
>     }
> 
>     @Override
>     public boolean equals(Object object) {
>         // TODO: Warning - this method won't work in the case the id
> fields 
> are not set
>         if (!(object instanceof Client)) {
>             return false;
>         }
>         Client other = (Client) object;
>         if ((this.id == null && other.id != null) || (this.id != null && 
> !this.id.equals(other.id))) {
>             return false;
>         }
>         return true;
>     }
> 
>     @Override
>     public String toString() {
>         return "com.vasilikon.entity.Client[id=" + id + "]";
>     }
> 
> }
> 
> package com.vasilikon.entity;
> 
> import java.util.List;
> import javax.ejb.LocalBean;
> import javax.ejb.Stateless;
> import javax.persistence.EntityManager;
> import javax.persistence.PersistenceContext;
> import javax.persistence.Query;
> import javax.persistence.criteria.CriteriaQuery;
> import javax.persistence.criteria.Root;
> 
> /**
>  *
>  * @author varleyr
>  */
> @Stateless
> @LocalBean
> public class ClientFacade {
>     @PersistenceContext(unitName = "Devere")
>     private EntityManager em;
> 
>     public void create(Client client) {
>         em.persist(client);
>     }
> 
>     public void edit(Client client) {
>         em.merge(client);
>     }
> 
>     public void remove(Client client) {
>         em.remove(em.merge(client));
>     }
> 
>     public Client find(Object id) {
>         return em.find(Client.class, id);
>     }
> 
>     public List<Client> findAll() {
>         CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
>         cq.select(cq.from(Client.class));
>         return em.createQuery(cq).getResultList();
>     }
> 
>     public List<Client> findRange(int[] range) {
>         CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
>         cq.select(cq.from(Client.class));
>         Query q = em.createQuery(cq);
>         q.setMaxResults(range[1] - range[0]);
>         q.setFirstResult(range[0]);
>         return q.getResultList();
>     }
> 
>     public int count() {
>         CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
>         Root<Client> rt = cq.from(Client.class);
>         cq.select(em.getCriteriaBuilder().count(rt));
>         Query q = em.createQuery(cq);
>         return ((Long) q.getSingleResult()).intValue();
>     }
> 
> }
> 
> /*
>  * To change this template, choose Tools | Templates
>  * and open the template in the editor.
>  */
> 
> package com.vasilikon.entity;
> 
> import java.io.Serializable;
> import javax.persistence.Entity;
> import javax.persistence.Id;
> import javax.persistence.ManyToOne;
> 
> /**
>  *
>  * @author varleyr
>  */
> @Entity
> public abstract class Phone implements Serializable {
> 
>     @Id
>     private int number;
> 
>     @ManyToOne
>     private Client client;
>     private static final long serialVersionUID = 1L;
> 
> 
> 
>     public Phone() {
> 
>     }
> 
>     public Phone(int number) {
>        this.number = number;
>     }
> 
>    public int getId() {
>        return number;
>    }
> 
>    public void setId(int id) {
>        this.number = id;
>    }
> 
>     public Client getClient() {
>         return client;
>     }
> 
>     public void setClient(Client client) {
>         this.client = client;
>     }
> 
> 
>     @Override
>     public String toString() {
>         return "com.vasilikon.entity.Phone[number=" + number + "]";
>     }
> 
>     @Override
>     public boolean equals(Object obj) {
>         if (obj == null) {
>             return false;
>         }
>         if (getClass() != obj.getClass()) {
>             return false;
>         }
>         final Phone other = (Phone) obj;
>         if (this.number != other.number) {
>             return false;
>         }
>         return true;
>     }
> 
>     @Override
>     public int hashCode() {
>         int hash = 7;
>         hash = 29 * hash + this.number;
>         return hash;
>     }
> 
>     
> 
>     
> 
> }
> 
> package com.vasilikon.entity;
> 
> import javax.persistence.Entity;
> 
> /**
>  *
>  * @author varleyr
>  */
> @Entity
> public class MobilePhone extends Phone {
> 
>     
>    
>     public MobilePhone() {
>         super();
>     }
> 
>     public MobilePhone(int number) {
>         super(number);
>     }
> 
> }
> 
> package com.vasilikon.entity;
> 
> import java.util.List;
> import javax.ejb.LocalBean;
> import javax.ejb.Stateless;
> import javax.persistence.EntityManager;
> import javax.persistence.PersistenceContext;
> import javax.persistence.Query;
> import javax.persistence.criteria.CriteriaQuery;
> import javax.persistence.criteria.Root;
> 
> /**
>  *
>  * @author varleyr
>  */
> @Stateless
> @LocalBean
> public class PhoneFacade {
>     @PersistenceContext(unitName = "Devere")
>     private EntityManager em;
> 
>     public void create(Phone phone) {
>         em.persist(phone);
>     }
> 
>     public void edit(Phone phone) {
>         em.merge(phone);
>     }
> 
>     public void remove(Phone phone) {
>         em.remove(em.merge(phone));
>     }
> 
>     public Phone find(Object id) {
>         return em.find(Phone.class, id);
>     }
> 
>     public List<Phone> findAll() {
>         CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
>         cq.select(cq.from(Phone.class));
>         return em.createQuery(cq).getResultList();
>     }
> 
>     public List<Phone> findRange(int[] range) {
>         CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
>         cq.select(cq.from(Phone.class));
>         Query q = em.createQuery(cq);
>         q.setMaxResults(range[1] - range[0]);
>         q.setFirstResult(range[0]);
>         return q.getResultList();
>     }
> 
>     public int count() {
>         CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
>         Root<Phone> rt = cq.from(Phone.class);
>         cq.select(em.getCriteriaBuilder().count(rt));
>         Query q = em.createQuery(cq);
>         return ((Long) q.getSingleResult()).intValue();
>     }
> 
> }
> 
> package com.vasilikon.processes;
> 
> import com.vasilikon.entity.Client;
> import com.vasilikon.entity.ClientFacade;
> import com.vasilikon.entity.Phone;
> import com.vasilikon.entity.PhoneFacade;
> import com.vasilikon.exceptions.PhoneNumberException;
> import javax.annotation.Resource;
> import javax.ejb.EJB;
> import javax.ejb.Stateless;
> import javax.ejb.LocalBean;
> import javax.ejb.SessionContext;
> 
> /**
>  *
>  * @author varleyr
>  */
> @Stateless
> @LocalBean
> public class ClientService {
>     
>     @EJB
>     ClientFacade clientFacade;
> 
>     @EJB
>     PhoneFacade phoneFacade;
> 
>     private SessionContext context;
> 
>     @Resource
>     public void setSessionContext(SessionContext context) {
>         this.context = context;
>     }
> 
>     public void create(Client client) throws PhoneNumberException {
> 
>         for (Phone phone : client.getPhones()) {
>             Phone exists = phoneFacade.find(phone.getId());
>            
>             if (exists != null) {
>                  context.setRollbackOnly();
>                 throw new PhoneNumberException("Phone number " +
> phone.getId()
>                         + " is already in use");
>             }
>         }
> 
>         clientFacade.create(client);
>     }
> 
>     public void delete(Client client) {
>         clientFacade.remove(client);
>     }
> }
> 
> 


-----
http://wiki.eclipse.org/User:James.sutherland.oracle.com James Sutherland 
http://www.eclipse.org/eclipselink/
 EclipseLink ,  http://www.oracle.com/technology/products/ias/toplink/
TopLink 
Wiki:  http://wiki.eclipse.org/EclipseLink EclipseLink , 
http://wiki.oracle.com/page/TopLink TopLink 
Forums:  http://forums.oracle.com/forums/forum.jspa?forumID=48 TopLink , 
http://www.nabble.com/EclipseLink-f26430.html EclipseLink 
Book:  http://en.wikibooks.org/wiki/Java_Persistence Java Persistence 
-- 
View this message in context: http://old.nabble.com/%28Long%29-Oddities-using-EclipseLink-2%2C-NetBeans-6.8%2C-EJB-and-GlassFish-3.0-tp27001987p27026876.html
Sent from the EclipseLink - Users mailing list archive at Nabble.com.



Back to the top