0

I am building a java REST application. Therefor I am using jboss on a wildfly 8 server.

The following code causes this exception: JBAS011469: Transaction is required to perform this operation (either use a transaction or extended persistence context)

@Path("/users")
@Stateless
public class UsersEndpoint {

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response create(User user) {

        try {
            this.checkUsername(user.getUsername());
            this.checkEmail(user.getEmail());
            return Response.ok(userDAO.create(user)).build();;
        } catch (IOException e) {
            return Response.status(Response.Status.NOT_ACCEPTABLE)
                           .entity(e.getMessage())
                           .build();

        } catch (Exception e) {
            return Response.status(Response.Status.NOT_ACCEPTABLE)
                           .entity(e.getMessage())
                           .build();
        }
    }

    @POST
    @Path("username")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.TEXT_HTML)
    public Response username(String username) {

        try {
            this.checkUsername(username);
            return Response.ok().build();
        } catch (Exception e) {
            return Response.status(Response.Status.NOT_ACCEPTABLE)
                           .entity(entity)
                           .build();
        }
    }

    @POST
    @Path("email")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.TEXT_HTML)
    public Response email(String email) {
        try {
            this.checkEmail(email);
            return Response.ok().build();
        } catch (Exception e) {
            return Response.status(Response.Status.NOT_ACCEPTABLE)
                           .entity(this.validator.validateError(null, e))
                           .build();
        }
    }

    private void checkUsername(String username) throws IOException {
        try {
            userDAO.get(username);
            throw new IOException("Username is taken allready.");
        }
        catch (IOException e) { throw e; }
        catch (Exception e) { System.out.println("Username can be used"); }
    }

    private void checkEmail(String email) throws IOException {
        try {
            userDAO.getByEmail(email);
            throw new IOException("Email is taken allready.");
        }
        catch (IOException e) { throw e; }
        catch (Exception e) { System.out.println("Email can be used"); }
    }
}

The public Response email(String email) and public Response username(String username) functions are working fine. The Problem seems to be the call of both functions through the public Response create(User user) function:

...
try {
    this.checkUsername(user.getUsername());
    this.checkEmail(user.getEmail());
    ...

So now when I have a correct username but a duplicate email the exception JBAS011469: Transaction is required to perform this operation (either use a transaction or extended persistence context) is going to be thrown in the userDAO.getByEmail(email). When I have a duplicate username instead the IOException("Username is taken allready.") is going to be thrown as expected.

When I change the order of those functions to:

...
try {
    this.checkEmail(user.getEmail());
    this.checkUsername(user.getUsername());
    ...

the same problem occurs but in userDAO.get(username) and with a correct email and a duplicate username.

EDIT

When I am removing throw new IOException("Username is taken allready."); in private void checkUsername(String username) throws IOException { } the second DAO call is working fine. So the problem seems to be the Exception that is thrown. How can I solve that?

My UserDAO

public interface UserDAO {
    public User create(User user) throws Exception;
    public User get(String username) throws Exception;
    public User getByEmail(String email) throws Exception;
}

My UserBean

@Stateless
@Remote(UserDAO.class)
public class UserBean implements UserDAO {

    // Injected database connection:
    @PersistenceContext private EntityManager em;

    @Override
    public User create(User user) throws Exception {
        em.persist(user);
        return user;
    }

    @Override
    public User get(String username) throws Exception {
        return em.createNamedQuery(User.QUERY_USERNAME, User.class)
                 .setParameter("userName", username)
                 .getSingleResult();
    }

    @Override
    public User getByEmail(String email) throws Exception {
        return em.createNamedQuery(User.QUERY_EMAIL, User.class)
                 .setParameter("email", email)
                 .getSingleResult();
    }
}
user2741109
  • 121
  • 13
  • The main problem is poorly designed code. You should refactor it to make it more clear and consistent. Also post your DAO layer code if you're experiencing a problem with it. – Justinas Jakavonis Jul 26 '16 at 08:04
  • @Justas Thank you. Can you please go more in detail when you say poorly designed code? – user2741109 Jul 26 '16 at 08:15
  • Why do throw exceptions to identify boolean expressions? Did you read/try this or other SO solution http://stackoverflow.com/questions/23300014/object-is-not-getting-persisted-using-jpa-jta-jboss-cdi? – Justinas Jakavonis Jul 26 '16 at 10:19

0 Answers0