Home > Software Development > javax.persistence.TransactionRequiredException (using Arquillian)

javax.persistence.TransactionRequiredException (using Arquillian)

I recently encountered javax.persistence.TransactionRequiredException when I am trying to perform some cleanup, on @After method in my unit test. I am currently playing with Arquillian (and it is such a great technology to complement Java EE).

The scenario is simple.

I have an Item entity, and I have ItemService. The service provides functionality to add an item and to retrieve it. That’s about it.

In unit test, for one reason or another, one might decide to clean up, or DELETE some item. However, in this case, I would very much like to keep my service layer clean, i.e. just because I happen to need a clean up on the test-side, I should not force my service to implement it. Perhaps another way to look at it is that this is my way to reduce coupling. The user of the service should knows about the service, and the service should not know about where it is being used. One direction, so to speak.

So, to start with, here’s the code:

ItemDistributionServiceTest

package com.dwuysan.service;

import com.dwuysan.entity.Item;
import com.dwuysan.util.EntityManagerProducer;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ArchivePaths;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
 * @author denywuy
 */
@RunWith(Arquillian.class)
public class ItemDistributionServiceTest {

    private Item item;
    @Inject
    private ItemService itemService;
    @Inject
    private EntityManager em;

    @Deployment
    public static JavaArchive createTestArchive() {
        return ShrinkWrap.create(JavaArchive.class)
                .addClass(Item.class)
                .addClass(ItemService.class)
                .addClass(EntityManagerProducer.class)
                .addAsManifestResource("test-persistence.xml", ArchivePaths.create("persistence.xml"))
                .addAsManifestResource("META-INF/beans.xml", ArchivePaths.create("beans.xml"))
                .addAsResource("ValidationMessages.properties");
    }

    @Before
    public void setup() {
        this.item = new Item();
        item.setCode("item01");
        item.setName("item01");
        item.setUom("piece");

        this.item = this.itemService.getItem(this.itemService.createItem(item));
    }

    @After
    public void cleanUp() throws Exception {
        this.em.remove(em.merge(this.item));
    }

    @Test
    public void testDistribute() throws Exception {
        /*
         * Test omitted
         */
    }
}

So, to DELETE the item, I directly use EntityManager#remove(...). However, that results in the following error:

Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 11.847 sec <<< FAILURE!
testDistribute(com.dwuysan.service.ItemDistributionServiceTest)  Time elapsed: 0.625 sec  <<< ERROR!
javax.persistence.TransactionRequiredException
	at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTxRequiredCheck(EntityManagerWrapper.java:163)
	at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTransactionScopedTxCheck(EntityManagerWrapper.java:145)
	at com.sun.enterprise.container.common.impl.EntityManagerWrapper.merge(EntityManagerWrapper.java:280)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

same as above

After further reading, I found that we need to explicitly initiates transaction. So, the code change slightly to:

ItemDistributionServiceTest

package com.dwuysan.service;

// the rest of the imports go here
import javax.annotation.Resource;
import javax.transaction.UserTransaction;

@RunWith(Arquillian.class)
public class ItemDistributionServiceTest {

    private Item item;

    // the rest of the injections go here
    @Resource
    private UserTransaction utx;

    @Deployment
    public static JavaArchive createTestArchive() {
        // same as above
    }

    @Before
    public void setup() {
        // same as above
    }

    @After
    public void cleanUp() throws Exception {
        utx.begin();
        this.em.remove(em.merge(this.item));
        utx.commit();
    }

    @Test
    public void testDistribute() throws Exception {
        /*
         * Test omitted
         */
    }
}

Reference:

Kosi2801, 2009, EntityManager throws TransactionRequiredException on merge() in JBoss JSF bean, accessed 29 March 2013.

About these ads
  1. July 3, 2013 at 3:24 pm

    You can always use Arquillian Transaction Extension instead of relying on UTX. Also for persistence bits there is Arquillian Persistence Extension.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 34 other followers

%d bloggers like this: