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

On Wednesday 06 January 2010 16:23:43 James Sutherland wrote:
> I'm not sure what you intend to happen, also perhaps include an SQL trace.
>
Hi James

Thanks for taking the time to look at this for me. I'd love to have an SQL 
trace to see what's going on but when using the glassfish embedded container, 
it appears to be ignoring the logging properties in persistence.xml. I've 
tried both
<property name="eclipselink.logging.level" value="FINE"/> and
<property name="javax.persistence.logging.level="FINE"/>

I've also tried putting both these values into a map and used, for example;

Map<String,String> properties = new HashMap<String, String>();
properties.put("eclipselink.logging.level","FINE");
EJBContainer ejbc = EJBContainer.createEJBContainer(properties);

and I still get no  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.
> 

That bit seems to work. In the second test I see "client" get inserted into 
the database. "dupclient" never gets persisted. When I call the delete(client) 
I see "client" disappear from the database, but "dupclient" appears albeit 
with the firstName=null. I expected neither to be in the database when I'd 
finished.

Regards

> 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
> 


Back to the top