/*
* JBoss, Home of Professional Open Source
* Copyright 2010, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.acme.jpa.business;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.List;
import javax.ejb.EJB;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import com.acme.jpa.model.LineItem;
import com.acme.jpa.model.Record;
@RunWith(Arquillian.class)
public class RepositoryTestCase
{
@Deployment
public static Archive<?> createDeployment()
{
return ShrinkWrap.create(JavaArchive.class)
.addClasses(Record.class, LineItem.class,
JavaPersistenceHelper.class, JavaPersistenceHelperBean.class,
Repository.class, RepositoryBean.class)
.addAsManifestResource("test-persistence.xml", "persistence.xml");
}
@EJB
JavaPersistenceHelper helper;
@EJB
Repository repository;
private static List<Record> seedRecords;
private static long idOfFirstRecord;
@Before
public void seed_database()
{
// emulate @BeforeClass on instance
// nice if this was supported in Arquillian
// sucks that seedRecords has to be static
if (seedRecords == null)
{
seedRecords = helper.seed(true);
idOfFirstRecord = seedRecords.get(0).getId();
}
}
/**
* A lazy loading operation should succeed when performed inside the context
* of the transaction retrieving it. The type of persistence context does
* not matter in this case.
*/
@Test
public void lazy_load_should_succeed_within_transaction()
{
Record record = repository.retrieveById(Record.class, idOfFirstRecord, new EntityInitializer<Record>()
{
@Override
public Record initialize(Record record)
{
record.getLineItems().size();
return record;
}
});
int numLineItemsExpected = 1;
assertEquals(numLineItemsExpected, record.getLineItems().size());
}
/**
* The entity should remain managed outside of an active stateful EJB when
* the entity is retrieved from an extended persistence context owned by that EJB.
*/
@Test
public void entity_should_be_managed_by_extended_pc_outside_active_ejb()
{
Record record = repository.retrieveById(Record.class, idOfFirstRecord);
assertTrue(repository.isManaging(record));
}
/**
* The entity should not be managed outside of an active stateful EJB when
* the entity is retrieved from a transaction-scoped persistence context owned by that EJB.
*/
@Test
public void entity_should_not_be_managed_by_transaction_scoped_pc_outside_active_ejb()
{
Record record = helper.retrieveById(Record.class, idOfFirstRecord);
assertFalse(helper.isManaging(record));
}
/**
* A lazy loading operation should succeed outside of an active stateful EJB
* when the entity is retrieved by an extended persistence context owned by
* that EJB.
*/
@Test
public void lazy_load_should_succeed_outside_of_active_ejb_with_extended_pc()
{
Record record = repository.retrieveById(Record.class, idOfFirstRecord);
int numLineItemsExpected = 1;
int numLineItemsActual = 0;
try
{
numLineItemsActual = record.getLineItems().size();
}
catch (Exception e)
{
}
assertEquals(numLineItemsExpected, numLineItemsActual);
}
/**
* A lazy loading operation should fail outside of a stateful EJB
* which has been removed. The persistence context is no longer
* available at this point.
*/
@Test
public void lazy_load_should_fail_outside_of_removed_ejb()
{
Record record = repository.retrieveById(Record.class, idOfFirstRecord);
repository.close();
// Some JPA providers (EclipseLink) allow LAZY relationships to be accessed after session is closed
int numLineItemsExpected = helper.isLazyLoadingPermittedOnClosedSession() ? 1 : 0;
int numLineItemsActual = 0;
try
{
numLineItemsActual = record.getLineItems().size();
}
catch (Exception e)
{
}
assertEquals(numLineItemsExpected, numLineItemsActual);
}
/**
* A lazy loading operation should fail outside of an EJB when the entity is
* retrieved by a transaction-scoped persistence context owned by that EJB.
* Certain JPA providers (e.g., EclipseLink) allow lazy relationships to be
* accessed after the session is closed.
*/
@Test
public void lazy_load_should_fail_outside_transaction_when_entity_retrieved_by_transaction_scoped_pc()
{
Record record = helper.retrieveById(Record.class, idOfFirstRecord);
assertFalse(helper.isManaging(record));
// Some JPA providers (e.g., EclipseLink) allow lazy relationships to be accessed after session is closed
int numLineItemsExpected = helper.isLazyLoadingPermittedOnClosedSession() ? 1 : 0;
int numLineItemsActual = 0;
try
{
numLineItemsActual = record.getLineItems().size();
}
catch (Exception e)
{
}
// verify the line items can't be fetched outside of EJB
assertEquals(numLineItemsExpected, numLineItemsActual);
}
/**
* A dirty (outstanding) change to an entity should be flushed when a transactional
* method is invoked on a stateful EJB which has an extended persistence context
* that is managing the entity.
*/
@Test
public void dirty_change_should_be_flushed_by_extended_pc_when_transactional_method_on_same_ejb_called()
{
Record record = repository.retrieveById(Record.class, idOfFirstRecord);
assertTrue(repository.isManaging(record));
String name = record.getName();
record.setName(name + "-renamed");
repository.update(record);
List<Record> results = repository.retrieveByQuery(Record.class, "select r from Record r where r.name = ?1", name + "-renamed");
assertEquals(1, results.size());
}
/**
* A dirty (outstanding) change to an entity should be flushed when any
* transactional method is invoked when an extended persistence context is
* managing the entity.
*/
@Test
public void dirty_change_should_be_flushed_by_extended_pc_when_transactional_method_on_another_ejb_called()
{
Record record = repository.retrieveById(Record.class, idOfFirstRecord);
assertTrue(repository.isManaging(record));
assertFalse(helper.isManaging(record));
String name = record.getName();
record.setName(name + "-renamed");
helper.transact();
List<Record> results = repository.retrieveByQuery(Record.class, "select r from Record r where r.name = ?1", name + "-renamed");
assertEquals(1, results.size());
}
}