This discussion is archived
1 2 Previous Next 23 Replies Latest reply: Jan 18, 2013 7:32 AM by morellik RSS

Remove JPA related entity

morellik Newbie
Currently Being Moderated
Dear all,

I've a problem to remove a related JPA entity, using eclipse persistence, glassfish 3.1.2 and PostgreSQL; Netbeans like IDE.
These are my entities:
public class User implements Serializable {
    @Id
    @Column(unique = true, nullable = false, length = 128)
    private String email;
    @Column(nullable = false, length = 128)
    private String firstName;
    @Column(nullable = false, length = 128)
    private String lastName;
    @Column(nullable = false, length = 128) //sha-512 + hex
    private String password;
    @ElementCollection(targetClass = Group.class)
    @CollectionTable(name = "USERS_GROUPS",
    joinColumns =
    @JoinColumn(name = "email", nullable = false),
    uniqueConstraints = {
        @UniqueConstraint(columnNames = {"email", "groupname"})})
    @Enumerated(EnumType.STRING)
    @Column(name = "groupname", length = 64, nullable = false)
    private List<Group> groups;
    @OneToMany(cascade = {CascadeType.PERSIST,
        CascadeType.MERGE,CascadeType.REMOVE})
    @JoinColumn(name="owner_fk") 
    private List<Printer> printer;
public class Printer implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
    private String description;
    private String identifier;
    @OneToOne
    private Firmware firmware;
    @ManyToOne
    private User owner;
This is a part of jsf page where I select the printer to remove:
      <h:form>
                <h:dataTable value="#{printerController.printerList}" var="pr" >
                    <h:column>
                        <f:facet name="header">
                            <h:outputText value="Name" />
                        </f:facet>
                        <h:outputText value="#{pr.name}" /> 
                    </h:column>
                    <h:column>
                        <f:facet name="header">
                            <h:outputText value="Description" />
                        </f:facet>
                        <h:outputText value="#{pr.description}" />
                    </h:column>
                    <h:column>
                        <f:facet name="header">
                            <h:outputText value="Identifier" />
                        </f:facet>
                        <h:outputText value="#{pr.identifier}" />
                    </h:column>
                    <h:column>
                        <f:facet name="header">
                            <h:outputText value="Select to remove" />
                        </f:facet>
                            <h:selectOneRadio id="id" value="id" >
                                <f:selectItem itemValue="#{pr.id}" />
                            </h:selectOneRadio>
                            <h:commandButton value="Remove"  style="margin-right:20px;" action="#{printerController.removePrinter}"/>  
                    </h:column>
                </h:dataTable>
                </h:form>
This is the last attempt to solve the problem (printerController.java).
 FacesContext context = FacesContext.getCurrentInstance();
    HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
    Principal p = request.getUserPrincipal();

    public String removePrinter() {
        Long id = printer.getId();
        String email = p.getName();
        User user = usersEJB.find(email);
        printerEJB.remove(id, user);
        addMessage("Printer removed");
        return "listPrinter";
    }
This is the part of printerEJB.java that could remove the printer:
 public void remove(Long id, User user) {
        Printer printer = find(id);
        if (printer != null) {
            em.getTransaction().begin();
            user.setPrinter(null);
            printer.setOwner(null);
            em.remove(printer);
            em.getTransaction().commit();
       }
    }

public Printer find(int id) {
        return em.find(Printer.class, id);
    }
No errors, no warning, no messages and the entity isn't removed. I don't understand where is the problem.

Thanks for your help.
  • 1. Re: Remove JPA related entity
    gimbal2 Guru
    Currently Being Moderated
    morellik wrote:
    This is the part of printerEJB.java that could remove the printer:
    public void remove(Long id, User user) {
    Printer printer = find(id);
    if (printer != null) {
    em.getTransaction().begin();
    user.setPrinter(null);
    printer.setOwner(null);
    em.remove(printer);
    em.getTransaction().commit();
    }
    }
    The fact that you start your own transaction is highly irregular. If you want to successfully remove an entity using JPA remove() it should be an already managed one, so when you call find() there should already be a transaction. Since apparently it is an EJB, I would assume you're using container managed transactions and you don't ever need to start and commit your own transaction.

    So the code is odd and likely subject to bad design. But for now it is likely going to work when you change it to this:
    public void remove(Long id, User user) {
            em.getTransaction().begin();
    
            Printer printer = find(id);
            if (printer != null) {
                user.setPrinter(null);
                printer.setOwner(null);
                em.remove(printer);
           }
           em.getTransaction().commit();
        }
    Probably those setPrinter() and setOwner() calls are also not needed by the way.
  • 2. Re: Remove JPA related entity
    morellik Newbie
    Currently Being Moderated
    Thank you for your answer. I find that example on internet. I tried your suggestion but the problem isn't solved. The entity wasn't removed.
  • 3. Re: Remove JPA related entity
    gimbal2 Guru
    Currently Being Moderated
    Works fine for me. In stead of copying code off the internet, learn how to use JPA so you can write your own code. "Pro JPA 2" is a good book for that purpose.
  • 4. Re: Remove JPA related entity
    morellik Newbie
    Currently Being Moderated
    Thanks, I'll read the book. But in the mean time is there a way to know why the entity isn't removed?
  • 5. Re: Remove JPA related entity
    r035198x Pro
    Currently Being Moderated
    You only showed fragments of your controller logic so anything could be happening there ... maybe the removePrinter method is not being called at all, maybe an exception is happening and you are swallowing it somewhere. Only you have the full code at the moment so only you can say. And before you post it all here, put some logging statements and check them to see which parts of your code are executing and what values are reaching (or not) where.
  • 6. Re: Remove JPA related entity
    morellik Newbie
    Currently Being Moderated
    I put some logging statements and seems that the removePrinter method isn't called.
    I use this method to display listPrinters.xhtml that I wrote in my first post
      public String listPrinters() {
            log.log(Level.SEVERE, "listPrinter");
            userPrinter = usersEJB.find(p.getName());
            printerList = printerEJB.getByOwner(userPrinter);
            return "listPrinters";
        }
    In the listPrinters I choose a printer and I press [remove] button to call printerController.removePrinter passing the id of the printer. But putting a logging in this method to print something, I don't see the message in the console. So I think that the method isn't called. Someone can tell me why?
  • 7. Re: Remove JPA related entity
    r035198x Pro
    Currently Being Moderated
    This could be due to any of several reasons that you need to investigate
    1.) Maybe your logger is not setup to print out correctly, try plain sysouts to verify that the method is indeed not being called
    2.) The method is not being found from the JSF page (in this case I'd expect you to be seeing an exception) maybe because the bean and method names are not matching
    3.) Maybe your page is not firing it's submit due to some other problems, perhaps javascript related
  • 8. Re: Remove JPA related entity
    morellik Newbie
    Currently Being Moderated
    r035198x wrote:
    This could be due to any of several reasons that you need to investigate
    1.) Maybe your logger is not setup to print out correctly, try plain sysouts to verify that the method is indeed not being called
    I put other logger to see if it works and I see the messages in the glassfish console.
    2.) The method is not being found from the JSF page (in this case I'd expect you to be seeing an exception) maybe because the bean and method names are not matching
    Exactly, I expect an exception in this case. Moreover if I write a non-existent method, Netbeans reports that.
    3.) Maybe your page is not firing it's submit due to some other problems, perhaps javascript related
    I don't use javascript for the moment.

    I'm going crazy for this problem :-((
  • 9. Re: Remove JPA related entity
    r035198x Pro
    Currently Being Moderated
    morellik wrote:
    I put other logger to see if it works and I see the messages in the glassfish console.
    What messages do you see? None from your method?
  • 10. Re: Remove JPA related entity
    morellik Newbie
    Currently Being Moderated
    I'm new to Java EE so another question is if my program design is correct. The flow is the following:

    Entities -> Beans (that persist, remove, query the entities) -> controllers (that call Beans methods and render JSF pages, I find the term controller in the book "Beginning Java EE 6 Platform with GlassFish 3") -> JFS pages

    Because I noticed a strange (for me) behaviour.. I have the following JSF that simulate a menu (in the future should be a real menu):
                        <h:form>
                            <table>
                                <thead>
                                    <th>Printers</th><th>Firmware</th>
                                </thead>
                                <tbody>
                                    <tr>
                                        <td>
                                            <h:commandLink action="#{printerController.createPrinter}" value="Create Printer" />
                                        </td>
                                        <td>
                                            <h:commandLink action="#{firmwareController.newFirmware}" value="New Firmware" />
                                        </td>
                                     </tr>
                                    <tr>
                                        <td>
                                            <h:commandLink action="#{printerController.listPrinters}" value="List Printers" />
                                        </td>
    
                                        <td>
                                            <h:commandLink action="#{firmwareController.listFirmware}" value="List Firmwares" />
                                        </td>
                                    </tr>
                                    <tr>
                                         <td>
                                             <h:commandLink action="#{printerController.searchPrinter}" value="Search Printer" />
                                        </td>
                                        <td>
                                            <h:commandLink action="#{firmwareController.searchFirmware}" value="Search Firmware" />
                                        </td>
                                        <td><h:commandLink action="#{userController.logout}" value="Logout" /></td>
                                    </tr>
    If I click on "List Printers" I call:
    public String listPrinters() {
            log.log(Level.SEVERE, "listPrinter");
            userPrinter = usersEJB.find(p.getName());
            printerList = printerEJB.getByOwner(userPrinter);
            return "listPrinters?faces-redirect=true";
        }
    That display an empty list. I have to remove faces-redirect=true to display something. In other cases I have to put faces-redirect=true to display the page.
    Is it correct using a controller to query and pass the results in a JSF page?

    Edited by: morellik on Jan 18, 2013 1:55 AM
  • 11. Re: Remove JPA related entity
    morellik Newbie
    Currently Being Moderated
    r035198x wrote:
    morellik wrote:
    I put other logger to see if it works and I see the messages in the glassfish console.
    What messages do you see? None from your method?
    I wrote a log in each method that print the name of the method. I see the print of all method except for the removePrinter..
  • 12. Re: Remove JPA related entity
    r035198x Pro
    Currently Being Moderated
    Since your commandButton is inside a datatable, verify that you are not running into this issue:http://stackoverflow.com/questions/8034428/hcommandbutton-not-working-inside-hdatatable
  • 13. Re: Remove JPA related entity
    morellik Newbie
    Currently Being Moderated
    r035198x wrote:
    Since your commandButton is inside a datatable, verify that you are not running into this issue:http://stackoverflow.com/questions/8034428/hcommandbutton-not-working-inside-hdatatable
    Yeah!!! You are ready. Now the removePrinter is called. But now I've a couple of related problems. I receive a javax.ejb.EJBException:

    Exception Description: Cannot use an EntityTransaction while using JTA.

    If I comment the transaction lines in the EJB:
    public void remove(Long id, User user) {
            //em.getTransaction().begin();
            Printer printer = find(id);
            if (printer != null) {
               
               // user.setPrinter(null);
               // printer.setOwner(null);
                em.remove(printer);
          
            }
            //em.getTransaction().commit();
        }
     public Printer find(Long id) {
            return em.find(Printer.class, id);
        }
    I receive another exception:

    java.lang.IllegalArgumentException: An instance of a null PK has been incorrectly provided for this find operation.

    I changed the JSF like follow:
      <h:column>
                            <f:facet name="header">
                                <h:outputText value="Select to remove" />
                            </f:facet>
                            <h:selectOneRadio id="id" value="#{printerController.printer.id}" >
                                    <f:selectItem itemValue="#{pr.id}" />
                                </h:selectOneRadio>
                                
                        </h:column>
                    </h:dataTable>
                        <h:commandButton value="Remove"  style="margin-right:20px;" action="#{printerController.removePrinter}"/>  
                    </h:form>
    And the controller:
     public String removePrinter() {
             Long id = printer.getId();
            String m = "removePrinter: " + id;
            log.log(Level.SEVERE, m);
            String email = p.getName();
            User user = usersEJB.find(email);
            printerEJB.remove(id, user);
            addMessage("Printer removed");
            return "listPrinter";
        }
    The log print removePrinter: null

    I'm thinking to stop to study Java EE, seems too complicate. :-((
  • 14. Re: Remove JPA related entity
    r035198x Pro
    Currently Being Moderated
    >
    Yeah!!! You are ready. Now the removePrinter is called. But now I've a couple of related problems. I receive a javax.ejb.EJBException:

    Exception Description: Cannot use an EntityTransaction while using JTA.
    When you are using JTA (as specified in your persistence.xml) the container starts and commits transactions for you so you are not allowed to do it again using EntityTransaction. You should be happy about this because using EntityTransaction yourself is hard.
    >
    >
    I receive another exception:

    java.lang.IllegalArgumentException: An instance of a null PK has been incorrectly provided for this find operation.
    Print out and see what values you are passing to the EntityManager. The error message already gives you a hint.
    >
    I changed the JSF like follow:
    ..

    The log print removePrinter: null
    You are using
    Long id = printer.getId();
    In that code you are getting the id from the printer object but where did you set that value? That printer object just has a null value because the id was never set. You probably mean to get that value from the jsf page but you never passed any values to it at all.
    I'm thinking to stop to study Java EE, seems too complicate. :-((
    Maybe it is but I think it will be much easier to start by getting the JavaEE tutorial (you can download it for free) and going through it to understand how things work. The tutorial will show you how to pass values from JSF pages to controller methods and how to access values from various scopes including explaining how everything fits together.
1 2 Previous Next

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points