In my service, have handled DataIntegrityViolationException when calling myCrudRepository.saveAndFlush to handle concurrent persist (insertion) requests. It works and I can catch the exception. After this, I prefer to make sure if the exception is exactly because entity already exists, not due to any other possible unknown issues. So, I call myCrudRepository.exists(entity.getId()) , but DataIntegrityViolationException is thrown again.
Here is my simple code:
private void save(final Employee entity) throws MyAppException {
try{
this.myCrudRepository.saveAndFlush(entity);
}catch (org.springframework.dao.DataIntegrityViolationException e){
// check if the error is really because the entity already exists
// entity.getId() is already generated before any save. it's like National ID
boolean exists = this.myCrudRepository.exists(entity.getId()); // DataIntegrityViolationException is thrown here again!
if (exists)
throw new MyAppException(HttpStatus.CONFLICT, "Entity already exists.");
else
throw e;
}
}
But if I use findOne instead of exists, it works fine. It's somehow strange, but of course it has a technical reason that I'm not good enough to make a guess.
Any idea? Thanks in advance.
The problem is when you are using Transactional method and after the method returns the transaction will auto commit and hibernate will wrap up the exceptions into another one. Actually the exception is occurring when transaction commits and at that time you are out of that method already. To catch the exception from inside the method you can simply use em.flush() after this.myCrudRepository.saveAndFlush(entity);.
I'm cleaning up some warnings, and I came up on some code using the connection() method of StatelessSession, whose deprecation doc says they missed it when deprecation the same method on Session.
Now, the answers to this question point to the doWork method on Session, but no such method exists on StatelessSession. So, how is one supposed to fix this deprecation?
The StatelessSession.connection() method goal was to:
Return the current JDBC connection associated with this instance.
The StatelessSession inherits this method from SessionImplementor, which is not deprecated, so it's safe to use it. Even if it's going to be removed from StatelessSession, you will still have this method from the SessionImplementor.
You can do something like this:
StatelessSession statelessSession = HibernateUtil.getSessionFactory().openStatelessSession();
try {
((StatelessSessionImpl) statelessSession).getJdbcConnectionAccess().obtainConnection().setTransactionIsolation(TRANSACTION_REPEATABLE_READ);
} catch (SQLException e) {
e.printStackTrace();
}
I'm experiencing a weird/odd behavior. I'm working on a project which is a web app using Java EE. It is deployed on GlassFish 3.1.1 using Eclipselink 2.3 persistence services. Everything is on Eclipse, Windows 7 professional 64 bit, JDK + JVM 64 bit.
I get a business object to work with. First I set the corresponding entity. Everything is fine up to the invocation of a method. If I debug inside this, the entity suddenly becomes null.
Before this invocation the entity is instantiated.
The code is this:
// get my entity
tramiteProxy = ejbTramiteFactory.getEntity(tramite);
// get corresponding business thru factory
IRegistrableInLiquidador registrableInLiquidadorBusiness = (IRegistrableInLiquidador) ejbTramiteFactory.getCBusiness(tramiteProxy);
// invoke business
// up to here everything is fine, you can inspect business variable and it shows correct, entity is instantiated as expected
registrableInLiquidadorBusiness.registrarNovedadInIntegrador();
Now we go debugging inside the business object (registrableInLiquidadorBusiness):
// Here if one checks the entity it became null !!!
public void registrarNovedadInIntegrador() throws CException {
try {
CIntegradorBusiness ejbIntegradorBusiness = CCTX
.getEJB(CIntegradorBusiness.class);
// Here's the problem: getEntity() returns null, the entity of this business object became *magically* null
ejbIntegradorBusiness.registrarNovedad(getEntity(),null);
} catch (Exception e) {
throw new CException(1, e);
}
}
I must add that the object entity is a variable declared in the father of this business, from which it extends.
So I don't know what else to try. I looked at every single line of code that has to do with this for finding any mistake to no avail.
The next step would probably be downloading the Eclipselink source and debug it to see what's going on behind the scenes, though I don't even know if it has anything to do with this.
Any advice would be greatly appreciated.
I have a code that saves a bean, and updates another bean in a DB via Hibernate. It must be do in the same transaction, because if something wrong occurs (f.ex launches a Exception) rollback must be executed for the two operations.
public class BeanDao extends ManagedSession {
public Integer save(Bean bean) {
Session session = null;
try {
session = createNewSessionAndTransaction();
Integer idValoracio = (Integer) session.save(bean); // SAVE
doOtherAction(bean); // UPDATE
commitTransaction(session);
return idBean;
} catch (RuntimeException re) {
log.error("get failed", re);
if (session != null) {
rollbackTransaction(session);
}
throw re;
}
}
private void doOtherAction(Bean bean) {
Integer idOtherBean = bean.getIdOtherBean();
OtherBeanDao otherBeanDao = new OtherBeanDao();
OtherBean otherBean = otherBeanDao.findById(idOtherBean);
.
. (doing operations)
.
otherBeanDao.attachDirty(otherBean)
}
}
The problem is:
In case that
session.save(bean)
launches an error, then I get AssertionFailure, because the function doOtherAction (that is used in other parts of the project) uses session after a Exception is thrown.
The first thing I thought were extract the code of the function doOtherAction, but then I have the same code duplicate, and not seems the best practice to do it.
What is the best way to refactor this?
It's a common practice to manage transactions at one level above DAOs, in services or other business logic classes. That way you can, based on the business/service logic, in one case do two DAO operations in one transaction and, in another case, do them in separate transactions.
I'm a huge fan of Declarative Transaction Management. If you can spare the time to get it working (piece of cake with an Application Server such as GlassFish or JBoss, and easy with Spring). If you annotate your business method with #TransactionAttribute(REQUIRED) (it can even be set to be done as default) and it calls the two DAO methods you will get exactly what you want: everything gets committed at once or rolled back over an Exception.
This solution is about as loosely coupled as it gets.
The others are correct in that they take in to account what are common practice currently.
But that doesn't really help you with your current practice.
What you should do is create two new DAO methods. Such as CreateGlobalSession and CommitGlobalSession.
What these do is the same thing as your current create and commit routines.
The difference is that they set a "global" session variable (most likely best done with a ThreadLocal). Then you change the current routines so that they check if this global session already exists. If your create detects the global session, then simply return it. If your commit detects the global session, then it does nothing.
Now when you want to use it you do this:
try {
dao.createGlobalSession();
beanA.save();
beanb.save();
Dao.commitGlobalSession();
} finally {
dao.rollbackGlobalSession();
}
Make sure you wrap the process in a try block so that you can reset your global session if there's an error.
While the other techniques are considered best practice and ideally you could one day evolve to something like that, this will get you over the hump with little more than 3 new methods and changing two existing methods. After that the rest of your code stays the same.
I just want to create an object of class, but got this error when debugging. Can anybody tell me what the problem is? The location of this code is in some Spring(2.5) Service class.
There is a similar problem: OJB Reference Descriptor 1:0 relationship? Should I set auto-retrieve to false?
Thanks a lot~
The root cause is that when debugging the java debug interface will call the toString() of your class to show the class information in the pop up box, so if the toString method is not defined correctly, this may happen.
I also had a similar exception when debugging in Eclipse. When I moused-over an object, the pop up box displayed an com.sun.jdi.InvocationException message. The root cause for me was not the toString() method of my class, but rather the hashCode() method. It was causing a NullPointerException, which caused the com.sun.jdi.InvocationException to appear during debugging. Once I took care of the null pointer, everything worked as expected.
Well, it might be because of several things as mentioned by others before and after. In my case the problem was same but reason was something else.
In a class (A), I had several objects and one of object was another class (B) with some other objects. During the process, one of the object (String) from class B was null, and then I tried to access that object via parent class (A).
Thus, console will throw null point exception but eclipse debugger will show above mentioned error.
I hope you can do the remaining.
For me the same exception was thrown when the toString was defined as such:
#Override
public String toString() {
return "ListElem [next=" + next + ", data=" + data + "]";
}
Where ListElem is a linked list element and I created a ListElem as such:
private ListElem<Integer> cyclicLinkedList = new ListElem<>(3);
ListElem<Integer> cyclicObj = new ListElem<>(4);
...
cyclicLinkedList.setNext(new ListElem<Integer>(2)).setNext(cyclicObj)
.setNext(new ListElem<Integer>(6)).setNext(new ListElem<Integer>(2)).setNext(cyclicObj);
This effectively caused a cyclic linked list that cannot be printed. Thanks for the pointer.
I was facing the same issue because I was using Lombok #Data annotation that was creating toString and hashcode methods in class files, so I removed #Data annotation and used specific #Gettter #Setter annotation that fixed my issue.
we should use #Data only when we need all #ToString, #EqualsAndHashCode, #Getter on all fields, and #Setter on all non-final fields, and #RequiredArgsConstructor.
I had the same issue once. In my case toString() method was badly created. TO be precise a static final variable was included in the toString method when a developer form my team was assigned code cleaning task and to add toString(), hashCode() code and equals() methods to domain objects where ever possible. but in of the classes because of over looking at it, he included final static variable that caused the "com.sun.jdi.InvocationException" this exception was visible on debugging only when I hovered over the object which has the exception.
I got similar exception in Eclipse. This was due to java.lang.StackOverflowError error. I had overriden toString() method in child class, having JoinColumn, which was returning string using object of parentclass, resulting in circular dependency. Try to remove that object from toString(), and it will work.
Disabling 'Show Logical Structure' button/icon of the upper right corner of the variables window in the eclipse debugger resolved it, in my case.
so I had same problem here. Found out that my domain instance was getting detached from the hibernate session. I used isAttached() to check and attached the domain using d.attach()
This was my case
I had a entity Student which was having many-to-one relation with another entity Classes (the classes which he studied).
I wanted to save the data into another table, which was having foreign keys of both Student and Classes. At some instance of execution, I was bringing a List of Students under some conditions, and each Student will have a reference of Classes class.
Sample code :-
Iterator<Student> itr = studentId.iterator();
while (itr.hasNext())
{
Student student = (Student) itr.next();
MarksCardSiNoGen bo = new MarksCardSiNoGen();
bo.setStudentId(student);
Classes classBo = student.getClasses();
bo.setClassId(classBo);
}
Here you can see that, I'm setting both Student and Classes reference to the BO I want to save. But while debugging when I inspected student.getClasses() it was showing this exception(com.sun.jdi.InvocationException).
The problem I found was that, after fetching the Student list using HQL query, I was flushing and closing the session. When I removed that session.close(); statement the problem was solved.
The session was closed when I finally saved all the data into table(MarksCardSiNoGen).
Hope this helps.
I have received com.sun.jdi.InvocationException occurred invoking method when I lazy loaded entity field which used secondary database config (Spring Boot with 2 database configs - lazy loading with second config does not work). Temporary solution was to add FetchType.EAGER.
There could be two reasons an element doesn't exist:
Bad xpath (//*[#id'forgotQuote])
Correct xpath but no element (//*[contains(text(),'This text is not in the page')])
Would you get com.sun.jdi.InvocationException in either case when you are running Debug and you hover your mouse over a reference to the WeBElement (this with Selenium and Java)???
We use the following, but can't distinguish if it returns false due to bad xpath or non-existent element (valid xpath syntax):
public static boolean isElementDisplayed(WebElement element) {
boolean isDisplayed = false;
try {
isDisplayed = element.isDisplayed();
} catch (NoSuchElementException e) {
;// No Worries
}
return isDisplayed;
}
Removing hashCode() and equals() solved my issue. In my case, I used Apache's commons-lang hash code and equals builders for creating non-static classes manually, so the compiler didn't throw any exception. But at runtime it caused the invocation exception.
In my case it was due to the object reference getting stale.
I was automating my application using selenium webdriver, so i type something into a text box and then it navigates to another page, so while i come back on the previous page , that object gets stale.
So this was causing the exception, I handled it by again initialising the elements -
PageFactory.initElements(driver, Test.class;
I also faced the same problem. In my case I was hitting a java.util.UnknownFormatConversionException. I figured this out only after putting a printStackTrace call. I resolved it by changing my code as shown below.
from:
StringBuilder sb = new StringBuilder();
sb.append("***** Test Details *****\n");
String.format("[Test: %1]", sb.toString());
to:
String.format("[Test: %s]", sb.toString());
I faced the same problem once. In my case it was because of overridden equals method. One values was coming null.