Smaller stacktrace: database exceptions - java

simple example, i have a user with a unique name in the database. Now i add a user with same name as an existing user. I get a very big exception- stacktrace for it. Can i reduce this output with a parameter from openjpa? I tried some of this, but nothing works: http://openjpa.apache.org/builds/1.0.1/apache-openjpa-1.0.1/docs/manual/ref_guide_logging.html
The other solution is to check the name before persisting, but i think thats an overhead or?
#ViewScoped
#ManagedBean
public class MyBean {
#EJB
private MyStateless stateless;
public void save(ActionEvent event){
try{
stateless.save();
}catch(Exception e){
System.out.println("####EXCEPTIOn");
}
}
}
#Stateless
#LocalBean
public class MyStateless{
#PersistenceContext(unitName = "pu")
private EntityManager em;
public void save() {
Person p = new Person(1, "Name");
em.persist(p);
}
}
org.apache.openjpa.persistence.EntityExistsException: The transaction has been rolled back. See the nested exceptions for details on the errors that occurred.
FailedObject: myejb.Person#1100245.......
2014-03-02T10:43:47.969+0100|Information: ####EXCEPTIOn
Here i get the javax.ejb.EJBException with the wrapped EntityExistsException

Related

For spring-batch transaction is not getting rolled back after exception

I am working on a spring-batch, where after reader and processor, writer is responsible to populate data to DB. Writer is calling Service which internally calls DAO layer. In method insertToDB() if some exception occurs the transaction is not being rolled back. PSB my code.
public class MyWriter{
#Autowired
private MyService myService;
#Override
public void write(List<? extends MyBO> list) {
try{
for(MyBO bo: list){
myService.insert(bo);
}
}
catch(Exception e){
log.error("Cant write to DB")
}
}
public class MyService{
#Autowired
private TableOneDAO tableOneDao;
#Autowired
private TableTwoDAO tableTwoDAO;
#Autowired
private TableThreeDAO tableThreeDAO;
public void insert(MyBO bo){
try{
// do other stuff of processing bo and create entity
MyEntityTableOne myentity1 = getEntityT1(bo);
MyEntityTableTwo myentity2 = getEntityT2(bo);
MyEntityTableThree myentity3 = getEntityT3(bo);
insertToDB(myEntity1,myEntity2,myEntity3);
}
catch(Exception e){
log.error("Error occured.");
throw new MyException("Error Blah blah occured");
}
}
#Transactional(value = "txn1")
public void insertToDB(MyEntityTableOne entity1, MyEntityTableTwo entity2, MyEntityTableThree entity3) {
try{
tableOneDao.insert(entity1);
tableTwoDAO.insert(entity2);
tableThreeDAO.insert(entity3);
}
catch(Exception e){
log.error("Error occured during insert to DB");
throw new MyException("Error Blah blah occured during DB insert");
}
}
The code goes to the catch block, but doesn't rollback records. If some error occurs during insert of Table2 then entry for Table1 is not rolled-back. And if occurs during table3 insertion then table1 and table2 records are not rolled-back.
If I move the #Transactional annotation to insert() method it works fine. What is root cause of this issue. What I have to do if I want to have transaction only on insertToDB() method.
I am trying to make it simple: To support #Transactional spring wraps the implementing class into a so called proxy and surrounds the method call / class with the transactional logic.
Now you are calling the #Transactional annotated method within the same class. Therefore the proxy is not invoked and the transactional does not work. When moving the annotation to your insert method you are invoking the method from outside of the class which means you invoke the method against the proxy.
Thats a limitation of Spring AOP (?) I think.
You can do something like following to achieve what you want:
public class MyService{
#Ressource
private MyService self;
...
self.insertToDB(myEntity1,myEntity2,myEntity3)
Your item writer will be already called in a transaction driven by Spring Batch and that you can configure at the step level by providing the transaction manager and transaction attributes. So there is no need to use #Transactional in the downstream service used by the writer.
You need to remove that annotation from MyService and it should work as expected.

Set pessimistic lock on entity with EntityManager

Consider the following situation:
We receive a request from a web service which updates our entity. Sometimes we might get two requests at (almost) the same time. We had situations in which our entity looked completely wrong, because of concurrent updates. The idea is to lock the entity pessimistic so that whenever the first request comes it instantly locks the entity and the second request can't touch it (Optimistic locking is no alternative for us). I wrote an integration test to check this behaviour.
I got an integration test which looks like the following:
protected static TestRemoteFacade testFacade;
#BeforeClass
public static void setup() {
testFacade = BeanLocator.lookupRemote(TestRemoteFacade.class, TestRemoteFacade.REMOTE_JNDI_NAME, TestRemoteFacade.NAMESPACE);
}
#Test
public void testPessimisticLock() throws Exception {
testFacade.readPessimisticTwice();
}
which calls the bean
#Stateless
#Clustered
#SecurityDomain("myDomain")
#RolesAllowed({ Roles.ACCESS })
public class TestFacadeBean extends FacadeBean implements TestRemoteFacade {
#EJB
private FiolaProduktLocalFacade produkt;
#Override
public void readPessimisticTwice() {
produkt.readPessimisticTwice();
}
}
with produkt being a bean itself
#Stateless
#Clustered
#SecurityDomain("myDomain")
#RolesAllowed({ Roles.ACCESS })
public class ProduktFacadeBean implements ProduktLocalFacade {
#Override
public void readPessimisticTwice() {
EntityManager entityManager = MyService.getCrudService().getEntityManager();
System.out.println("Before first try.");
entityManager.find(MyEntity.class, 1, LockModeType.PESSIMISTIC_WRITE);
System.out.println("Before second try.");
entityManager.find(MyEntity.class, 1, LockModeType.PESSIMISTIC_WRITE);
System.out.println("After second try.");
}
}
with
public class MyService {
public static CrudServiceLocalFacade getCrudService() {
return CrudServiceLookup.getCrudService();
}
}
public final class CrudServiceLookup {
private static CrudServiceLocalFacade crudService;
private CrudServiceLookup(){
}
public static CrudServiceLocalFacade getCrudService() {
if (crudService == null)
crudService = BeanLocator.lookup(CrudServiceLocalFacade.class, CrudServiceLocalFacade.LOCAL_JNDI_NAME);
return crudService;
}
public static void setCrudService(CrudServiceLocalFacade crudService) {
CrudServiceLookup.crudService = crudService;
}
}
#Stateless
#Local(CrudServiceLocalFacade.class)
#TransactionAttribute(TransactionAttributeType.MANDATORY)
#Interceptors(OracleDataBaseInterceptor.class)
public class CrudServiceFacadeBean implements CrudServiceLocalFacade {
private EntityManager em;
#Override
#PersistenceContext(unitName = "persistence_unit")
public void setEntityManager(EntityManager entityManager) {
em = entityManager;
}
#Override
public EntityManager getEntityManager() {
return em;
}
}
The problem that arises now is: If I start the integration test once with a breakpoint at System.out.println("Before second try."); and then start the integration test a second time, the latter one can still read MyEntity. Remarkable is that they were different instances (I made this observation on the instanceId in debug mode). This suggests that the entityManager didn't share his hibernate context.
I made the following observations:
Whenever I call a setter on entity and save it to the db, the lock is aquired. But this is not what I need. I need the lock without having modified the entity.
I tried the method entityManager.lock(entity, LockModeType.PESSIMISTIC_WRITE) as well, but the behaviour was the same.
I found Transaction settings in DBVisualizer. At the moment it is set to TRANSACTION_NONE. I tried all the others (TRANSACTION_READ_UNCOMMITTED, TRANSACTION_READ_COMMITTED, TRANSACTION_REPEATABLE_READ, TRANSACTION_SERIALIZABLE) as well, without any success.
Let the first thread read the entity, then the second thread read the same entity. Let the first tread modify the entity and then the second modify it. Then let both save the entity and whoever saves the entity last wins and no exceptions will be thrown.
How can I read an object pessimistic, that means: Whenever I load an entity from the db I want it to be locked immediately (even if there was no modification).
Both ways you describe ie.
em.find(MyEntity.class, 1, LockModeType.PESSIMISTIC_WRITE)
em.lock(entity, LockModeType.PESSIMISTIC_WRITE)
hold a lock on the related row in database but only for the the entityManager lifespan, ie. for the time of the enclosing transaction, the lock will be so automatically released once you've reached the end of the transaction
#Transactional()
public void doSomething() {
em.lock(entity, LockModeType.PESSIMISTIC_WRITE); // entity is locked
// any other thread trying to update the entity until this method finishes will raise an error
}
...
object.doSomething();
object.doSomethingElse(); // lock is already released here
Have you tried to set the isolation level in your application server?
To get a lock on a row no matter what you are trying to do afterwards (read/write), you need to set the isolation level to TRANSACTION_SERIALIZABLE.
Lock fails only if another thread is already holding the lock. You can take two FOR UPDATE locks on single row in DB, so it's not JPA-specific thing.

How to RollBack a transaction of an EntityManager injected by #PersistenceContext?

I am using JPA and i have an abstract class where i inject my entityManager and i have a generic method where i persist my oject to the database and in all my services class extends that abstract class but the issue is: sometimes i have to persist client and client details but if i have an exception in the persist of client , then my program persist client details that's why i look for a rollBack to call when i have a persist exception.
I khow that i can do like entityManager.getTransaction().rollback(); but if i manage my entity manager but in my case , it managed by the container.
Here is my abstract class:
public abstract class AbstractEntityFactory<E>{
protected static final transient Logger LOGGER = CommonLogger.getLogger(AbstractEntityFactory.class);
#PersistenceContext(unitName = "Test_PU")
#Transient
#XmlTransient
private transient EntityManager entityManager;
public E persist(final E arg0) {
LOGGER.debug("persist : Begin");
this.getEntityManager().persist(arg0);
this.getEntityManager().flush();
LOGGER.debug("persist : End");
return arg0;
}
}
NB: i have Jboss EAP6 as server
You can try using UserTransaction.rollback to roll back the current transaction.
Since your using a "container". I assume you mean something like wildfly,..
In that case I assume your using #Transactional somewhere. This annotation has an attribute called rollbackFor.
If I remember correctly the default setup does not rollback for RuntimeExceptions. So you might wana change this.
If you need to rollback manually use the UserTransaction. You should be able to get it via
public class SomeBean {
#Resource
private UserTransaction transaction;
}
you can use transaction rollback support annotation :
` #Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
public E persist(final E arg0) {
LOGGER.debug("persist : Begin");
this.getEntityManager().persist(arg0);
this.getEntityManager().flush();
LOGGER.debug("persist : End");
return arg0;
}`

Throwing an application exception causes TransactionalException

I am implementing an JEE7 web application. During my work i have found a problem with handling my custom exceptions.
I edited my account's property to have a non-unique login field. Then i invoked the AccountEditBean#editAccount() to run the editing process. When the process comes to AccountFacade#edit() i can see (in debug) that PersistenceException is caught and my custom NonUniqueException is thrown. The problem is, the exception is not propagated out of the facade class and it is not handled in AccountEditBean. Instead of that TransactionalException occurs right after throw:
WARNING: EJB5184:A system exception occurred during an invocation on
EJB ADMEndpoint, method: public void
pl.rozart.greatidea.adm.endpoints.ADMEndpoint.editAccount(pl.rozart.greatidea.entities.Account)
throws pl.rozart.greatidea.exceptions.BaseApplicationException
WARNING: javax.transaction.TransactionalException: Managed bean with
Transactional annotation and TxType of REQUIRES_NEW encountered
exception during commit javax.transaction.RollbackException:
Transaction marked for rollback.
Additional information:
NonUniqueException extends BaseApplicationException , which is marked as #ApplicationException(rollback=true).
Here's the code for the edit process:
AccountEditBean:
#Named(value = "accountEditBean")
#ViewScoped
public class AccountEditBean extends UtilityBean implements Serializable {
#Inject
ADMEndpointLocal admEndpoint;
private Account account;
public void editAccount() {
try {
admEndpoint.editAccount(this.account);
Messages.addInfo(ACCOUNT_DETAILS_FORM, KEY_CHANGES_SUCCESS);
} catch (NonUniqueException e) {
Messages.addError(ACCOUNT_DETAILS_FORM, e.getMessage());
} catch (BaseApplicationException e) {
Messages.addFatal(ACCOUNT_DETAILS_FORM, e.getMessage());
}
}
}
ADMEndpoint:
#Stateful
#Transactional(Transactional.TxType.REQUIRES_NEW)
#TransactionTracker
public class ADMEndpoint extends LoggingStateBean implements ADMEndpointLocal, SessionSynchronization {
#EJB(name = "ADMAccountFacade")
private AccountFacadeLocal accountFacade;
private Account account;
#Override
public void editAccount(Account account) throws BaseApplicationException {
this.account.setLogin(account.getLogin());
this.account.setEmail(account.getEmail());
accountFacade.edit(this.account);
}
}
ADMAccountFacade:
#Stateless(name = "ADMAccountFacade")
#Transactional(Transactional.TxType.MANDATORY)
#TransactionTracker
public class AccountFacade extends AbstractFacade<Account> implements AccountFacadeLocal {
#PersistenceContext(unitName = "myPU")
private EntityManager em;
#Override
public void edit(Account account) throws BaseApplicationException {
try {
em.merge(account);
em.flush();
} catch (PersistenceException e){
if(e.getMessage().contains(Account.CONSTRAINT_ACCOUNT_LOGIN_UNIQUE)){
throw new NonUniqueException(NonUniqueException.MSG_NON_UNIQUE_ACCOUNT_LOGIN, e);
}else{
throw new BaseDatabaseException(BaseDatabaseException.MSG_GENERAL_DATABASE_ERROR, e);
}
}
}
}
Do you know what could be the cause of the problem? It occurs in every of my facades, with all the custom exceptions.
I think you should change #Transactional to #TransactionAttribute because EJBs annotated with that. #Transactional is put on managedbean in java 7 not in EJBs...
I copied my comment here because i do not have enough points to squander :)
You are throwing an exception from a method whose invocation will be intercepted at runtime and additional logic wrapped around it:
transaction management;
exception handling.
Your exception cannot transparently jump over that logic, and the specification (probably) says a TransactionalException will be thrown, wrapping your original exception (again, probably---I am not that intimate with the details).

EJB3Unit save-function doesn't really save my entity

I am doing tests on an ejb3-project using ejb3unit session bean test. The following test will fail with the last assertNotSame() check.
public void testSave() {
Entity myEntity = new Entity();
myEntity.setName("name1");
myEntity = getBeanToTest().save(myEntity);
assertNotSame("id should be set", 0l, myEntity.getId());
// now the problem itself ...
int count = getBeanToTest().findAll().size();
assertNotSame("should find at least 1 entity", 0, count);
}
So, what is happening. The save(entity) method delivers my "persisted" object with an id set. But when I'll try to find the object using findAll() it won't deliver a single result. How can I get my ServiceBean.save method to work, so the persisted entity can be found?
Edit
My ServiceBean looks like this
#Stateless
#Local(IMyServiceBean.class)
public class MyServiceBean implements IMyServiceBean {
#PersistenceContext(unitName = "appDataBase")
private EntityManager em;
public Entity save(Entity entity) {
em.merge(entity);
}
public List<Entity> findAll() {
... uses Query to find all Entities ..
}
}
and for ejb3unit the ejb3unit.properties:
ejb3unit_jndi.1.isSessionBean=false
ejb3unit_jndi.1.jndiName=project/MyServiceBean/local
ejb3unit_jndi.1.className=de.prj.MyServiceBean
Here we go..
public void testSave() {
Entity myEntity = .. // create some valid Instance
// ...
EntityTransaction tx = this.getEntityManager().getTransaction();
try {
tx.begin();
myEntity = getBeanToTest().save(myEntity);
tx.commit();
} catch (Exception e) {
tx.rollback();
fail("saving failed");
}
// ...
}
maybe this'll help some of you.
Perhaps you don't have a running transaction, hence your entity isn't saved.
One option is to manually start the transaction by injecting a #PersistenceContext in the test, but better look for automatic transaction management in ejb3unit.

Categories