Hello.

I have a demo app where the user can enter people and save them to a database.  
Each person can have 0..* email addresses.  The user can also go to a seperate 
page where the people are listed and select one to edit (taking them back to 
the first screen, now pre-populated with the person data)

The following use cases work just fine:
* Save new person with and without emails
* Edit person with emails
* Edit person without emails, who formerly had emails
* Edit person (who had an email added, and removed before being saved)
* Save new person without email, go to list page, select the person, then edit 
them
* Etc.


What's odd is that in one scenario, it doesn't work.  That's if I create a new 
person, save them (without adding any emails), then modify them and save again 
(still without adding any emails).  If, at any point, I add an email, even 
without saving it, it works.

The error I get when this does happen is as such:
A collection with cascade="all-delete-orphan" was no longer referenced by the 
owning entity instance

Here's the relevant snippets of my code:

  | @Stateful
  | @Name("editPerson")
  | public class EditPersonForm implements EditPersonLocal {
  |     @PersistenceContext(type = EXTENDED)
  |     private EntityManager em;
  | 
  |     @In(required = false)
  |     @Out(scope = ScopeType.PAGE)
  |     private Person person;
  | 
  |     @In(required = false)
  |     @Out(required = false)
  |     private EmailAddress emailAddress;
  | 
  |     public void addEmail() {
  |             log.info("Adding email address #0", emailAddress.getUrl());
  |             person.addEmailAddress(emailAddress);
  | 
  |             //Blank the email address entry point
  |             emailAddress = new EmailAddress();
  |     }
  | 
  |     public void removeEmail(EmailAddress emailAddress) {
  |             log.info("Removing email address #0", emailAddress.getUrl());
  |             person.removeEmailAddress(emailAddress);
  |     }
  | 
  |     public void savePerson() {
  |             if (person.getId() != null){
  |                     em.merge(person);
  |             }
  |             else {
  |                     em.persist(person);
  |             }
  | 
  |             // Note that the id of our person was generated and populated.
  |             facesMessages.add("#0 was saved with an id of #1", 
person.getName(), person.getId());
  | 
  |             log.info(person.getName() + " was saved.");
  |     }
  | }
  | 


  |                     Name: 
  |                     <h:inputText value="#{person.name}" required="true"
  |                             requiredMessage="You need to enter a name" />
  |                     <h:outputText value="#{person.id}" />
  |                     <br />
  |                     <hr />                  
  |                     Emails:<br />
  |                     URL: <h:inputText value="#{emailAddress.url}" />
  |                     <h:commandButton action="#{editPerson.addEmail()}" 
value="Add email" />
  | 
  |                     <h:dataTable id="emailTable" 
value="#{person.emailAddresses}"
  |                             var="email" rendered="#{not empty 
person.emailAddresses}">
  |                             <h:column>
  |                                     <f:facet name="header">
  |                                             <h:outputText value="URL" />
  |                                     </f:facet>
  |                                     <h:outputText value="#{email.url}" />
  |                             </h:column>
  |                             <h:column>
  |                                     <f:facet name="header">
  |                                             <h:outputText value="Action" />
  |                                     </f:facet>
  |                                     <h:commandButton value="Remove"
  |                                             
action="#{editPerson.removeEmail(email)}" />
  |                             </h:column>
  |                     </h:dataTable>
  |                     <hr />
  |                     <h:commandButton value="Save" 
action="#{editPerson.savePerson()}" />
  |                     <h:commandButton value="New" 
action="#{editPerson.newPerson()}" />
  | 


  | @Entity
  | @Name("person")
  | public class Person {
  | 
  |     @Id @GeneratedValue
  |     private Long id;
  |     
  |     @NotNull
  |     private String name;
  |     
  |     @OneToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER, 
mappedBy="person")
  |     
@org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
  |     private Collection<EmailAddress> emailAddresses;
  |     
  |     public Long getId() {return id;}
  |     public void setId(Long id) {this.id = id;}
  |     
  |     public String getName() {return name;}
  |     public void setName(String name) {this.name = name;}
  |     
  |     public Collection<EmailAddress> getEmailAddresses() {
  |             return emailAddresses;
  |     }
  |     public void setEmailAddresses(Collection<EmailAddress> emailAddresses) {
  |             this.emailAddresses = emailAddresses;
  |     }
  |     public void addEmailAddress(EmailAddress email){
  |             if (emailAddresses == null) emailAddresses= new 
ArrayList<EmailAddress>();
  |             email.setPerson(this);
  |             emailAddresses.add(email);
  |     }
  |     public void removeEmailAddress(EmailAddress emailAddress){
  |             if (emailAddresses != null){
  |                     emailAddresses.remove(emailAddress);
  |             }
  |     }
  | }
  | 


  | @Entity
  | @Name("emailAddress")
  | public class EmailAddress {
  | 
  |     @Id @GeneratedValue
  |     private Long id;
  |     
  |     @NotNull
  |     private String url;
  |     
  |     @ManyToOne
  |     @JoinColumn(name="person_id")
  |     private Person person;
  |     
  |     public Long getId() {return id;}
  |     public void setId(Long id) {this.id = id;}
  |     
  |     public String getUrl() {
  |             return url;
  |     }
  |     public void setUrl(String url) {
  |             this.url = url;
  |     }
  |     
  |     public Person getPerson() {
  |             return person;
  |     }
  |     public void setPerson(Person person) {
  |             this.person = person;
  |     }
  | }
  | 

Now, I have found that if I put the following code right before the 
"em.merge(person)" (in the top code block), I no longer have this issue and it 
works.

  | if (person.getEmailAddresses() == null)
  |     person.setEmailAddresses(new ArrayList<EmailAddress>());
  | 

Is this a known issue?  Oh, and I apologize if this is isn't the correct forum 
for this, I wasn't sure if it was more EJB or Hibernate related.

View the original post : 
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4123200#4123200

Reply to the post : 
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4123200
_______________________________________________
jboss-user mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/jboss-user

Reply via email to