0

In my exploration of JPA, I have the code below (which I understand should not be used in production). Running my code produces the following error:

java.lang.IllegalStateException: 
Exception Description: Cannot use an EntityTransaction while using JTA.

The Resource code is as follows:

@Path("users")
public class UsersAPI {
    @Context
    UriInfo uriInfo;

    @Inject
    UserBean accountsBean;

    @GET
    @Path("deduplicate")
    public Response deduplicateDB(){
        List<UserProfile> profiles = accountsBean.getAll();
        int profilesNum = profiles.size();
        for(int i = 0; i < profilesNum; ++i){
            for(int k = 0; k < profilesNum; ++k){
                if(i != k){ //if it's not the same profile
                    if(profiles.get(i).getUsername().equals(profiles.get(k).getUsername())){
                        accountsBean.remove(profiles.get(k));
                        profiles.remove(k);
                    }
                }
                profilesNum = profiles.size();
            }
        }
        return Response.ok().build();
    }
}

The code in the ProfilesBean is as follows:

@Local
@Stateless
public class UserBean {
    @PersistenceContext
    EntityManager eManager;

    public void save(UserProfile data){
        eManager.merge(data);
    }

    public void remove(UserProfile data){
        eManager.getTransaction().begin();
        eManager.remove(data);
        eManager.getTransaction().commit();
    }

    public List<UserProfile> getAll(){
        Query q = eManager.createQuery("SELECT profile FROM Users profile");
        return (List<UserProfile>)q.getResultList();
    }
}

Here is the code for the Entity class:

@Entity(name="Users")
public class UserProfile {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    Long id;
    String password;
    @Column(unique=true)
    String username;

    public UserProfile(String username){
        setUsername(username);
    }
    public UserProfile(){
        this(null);
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
}

It seems like the error comes from my misusing the platform somehow. How can I fix this code and not misuse the platform in the future?

KG6ZVP
  • 3,610
  • 4
  • 26
  • 45

1 Answers1

1

If you are using JTA as transaction-type in persistence.xml file just leave JTA handles your transactions

public void remove(UserProfile data){
    eManager.remove(eManager.merge(data));
}

UPDATE: In a more clear solution you could use "find", but you need to provide the object id

public void remove(UserProfile data){
    UserProfile e = em.find(UserProfile.class, data.getId());
    eManager.remove(e);
}
Luca Montagnoli
  • 302
  • 1
  • 9
  • That's probably a good answer, but what is JTA? I'm not aware of having set such a thing under persistence.xml – KG6ZVP Mar 17 '16 at 00:22
  • Probably it's your default. As specification "In a Java EE environment, if this element is not specified, the default is JTA". In persistence.xml you specify whether it should be used JTA o RESOURCE_LOCAL to provide a datasource. With JTA the container provides the datasource. – Luca Montagnoli Mar 17 '16 at 00:39
  • I'll try and post back. – KG6ZVP Mar 17 '16 at 00:39
  • I now receive this error: java.lang.IllegalArgumentException: Entity must be managed to call remove: UserProfile – KG6ZVP Mar 17 '16 at 01:31
  • It's correct, to perform a remove operation you need the managed entity. Try this: "eManager.remove(eManager.merge(data));" – Luca Montagnoli Mar 17 '16 at 08:23
  • This fixed it! Thank you. – KG6ZVP Mar 17 '16 at 08:30
  • "Remove" works only with managed entities. The entity passed to the method is not handled by the persistence unit. "Merge" returns the managed Entity using your UserProfile object. – Luca Montagnoli Mar 17 '16 at 10:31
  • I see. Thanks for the clarification. – KG6ZVP Mar 17 '16 at 10:47