JPA Strange behaivor when updating embeddable - jpa

My problem is when iam trying to update an object with an embeddable class. If i watch the values, it seems the embeddable values are there. But the code throw an exception telling that that values are empty. And when i watch in the debugger, the object has de values but when i inspect the content in the exception, the object seems not having the values.
public abstract class ItemOrcamento extends EntidadeAuditavel {
#Embedded private ConfiguracaoColeta configuracaoColeta = new ConfiguracaoColeta();
}
And after the em.flush() it throws the exception InvalidStateException and when i search to look for the variables its appears this:

Related

Why JpaRepository doesn't commit to database when called from #SpringBootTest?

When repository.save(t) is called from my service, which is in turn called from my controller, all works just fine, and the object is inserted into the database table; But, when the service is called from my test class, Hibernate returns the created object but does not really flush the transaction into the database. I have tried using #Transactinal and #Commit in my test class and also on my #Test methods, but no difference in the result. I have also tried other solutions which involve using org.springframework.test.context.transaction.TestTransaction class, but any method call on this class throws an exception.
this is my super class for test:
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
public abstract class QaApplicationTest {
protected abstract void initializeTest() throws Exception;
protected abstract void cleanupTestEffects() throws Exception;
}
And this is my concrete test class:
public class RequestControllerTest extends QaApplicationTest {
#Autowired
private SiteService siteService;
#Autowired
private RequestService requestService;
#Test
#Transactional
public void givenObject_whenInsertToDB_thenCreated() throws Exception{
Site siteObject = siteService.save(siteObject); //Here I need a commit.
Request request = new Request(site.getId());
Request savedRequest = requestService.save(request); //Here database returns "Parent Key Not Found" error.
Assertions.assertTrue(savedRequest.getId()>0);
}
}
I know the #Transactional on test methods are used to roll back all the changes made inside the method, however, In my case, the changes are not even committed in the first place. And I have used #org.springframework.transaction.annotation.Transactional which is the correct annotation. I don't know which part I am doing wrong! Any idea?
My colleague found the issue; we had used a third-party library (Camunda) that had enabled batch-insert on Hibernate. So by disabling the batch operation the issue was resolved and the insert is actually taking place now. Not sure, why we faced this only in Spring Test and not in the main application though. if anyone has a comment, we appreciate it.

DI and inheritance

Another question appeared during my migration from an E3 application to a pure E4.
I got a Structure using inheritance as in the following pic.
There I have an invocation sequence going from the AbstractRootEditor to the FormRootEditor to the SashCompositeSubView to the TableSubView.
There I want to use my EMenuService, but it is null due to it can´t be injected.
The AbstractRootEditor is the only class connected to the Application Model (as a MPart created out of an MPartDescriptor).
I´d like to inject the EMenuService anyway in the AbstractSubView, otherwise I would´ve the need to carry the Service through all of my classes. But I don´t have an IEclipseContext there, due to my AbstractSubView is not connected with Application Model (Do I ?).
I there any chance to get the service injected in the AvstractSubView?
EDIT:
I noticed that injecting this in my AbstractSubView isn´t possible (?), so I´m trying to get it into my TableSubView.
After gregs comment i want to show some code:
in the AbstractRootEditor:
#PostConstruct
public final void createPartControl(Composite parent, #Active MPart mPart) {
...
ContextInjectionFactory.make(TableSubView.class, mPart.getContext());
First I got an Exception, saying that my TableSubView.class got an invalid constructor, so now the Constructor there is:
public TableSubView() {
this.tableInputController=null;
}
as well as my Field-Injection:
#Inject EMenuService eMenuService
This is kind of not working, eMenuService is still null
If you create your objects using ContextInjectionFactory they will be injected. Use:
MyClass myClass = ContextInjectionFactory.make(MyClass.class, context);
where context is an IEclipseContext (so you have to do this for every class starting from one that is injected by Eclipse).
There is also a seconds version of ContextInjectionFactory.make which lets you provide two contexts the second one being a temporary context which can contain additional values.

default JPA behavior for selecting non-existing entity

I'm writing some tests to make sure all the CRUD methods are working correctly. Every one of them are working fine, but it seems to be a little bit tricky to test the remove method.
In my test, I'm doing this:
// remove
a = dao.select(1); // previously inserted in the DB
dao.remove(a);
assertNull(dao.select(a.getId()));
And the DAO class (only select and remove):
#Override
public AtividadeComercial select(int id) {
return em.getReference(AtividadeComercial.class, id);
}
#Override
public void remove(AtividadeComercial e) {
EntityTransaction t = em.getTransaction();
boolean active = t.isActive();
if(!active)
t.begin();
em.remove(em.getReference(e.getClass(), e.getId()));
if(!active)
t.commit();
}
But the test is always throwing a javax.persistence.EntityNotFoundException on the line after remove. Is this the normal behavior or is something really wrong? Sorry if this seems to much obvious, but I couldn't find an answer to that.
getReference() will never return null. Read its documentation:
Get an instance, whose state may be lazily fetched. If the requested instance does not exist in the database, the EntityNotFoundException is thrown when the instance state is first accessed.
This method returns a proxy over an entity that is supposed to exist. It doesn't even make a database query to check if the entity exists: it assumes that it exissts. And if the proxy is initialized later, and the entity doesn't exist, then you'll get an EntityNotFoundException.

java.lang.IllegalArgumentException: Removing a detached instance com.test.User#5

I have a java EE project using JPA (transaction-type="JTA"), hibernate as provider. I write my beans to handle the CRUD things. The program running in JBOSS 7 AS.
I have an EntityManagerDAO :
#Stateful
public class EntityManagerDao implements Serializable {
#PersistenceContext(unitName = "dtdJpa")
private EntityManager entityManager;
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public Object updateObject(Object object) {
object = entityManager.merge(object);
return object;
}
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public void createObject(Object object) {
entityManager.persist(object);
}
public void refresh(Object object) {
entityManager.refresh(object);
}
public <T> T find(Class<T> clazz, Long id) {
return entityManager.find(clazz, id);
}
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public void deleteObject(Object object) {
entityManager.remove(object);
}
}
but when I invoke deleteObject, this exception comes out.
java.lang.IllegalArgumentException: Removing a detached instance com.test.User#5
How is this caused and how can I solve it?
EntityManager#remove() works only on entities which are managed in the current transaction/context. In your case, you're retrieving the entity in an earlier transaction, storing it in the HTTP session and then attempting to remove it in a different transaction/context. This just won't work.
You need to check if the entity is managed by EntityManager#contains() and if not, then make it managed it EntityManager#merge().
Basically, the delete() method of your business service class should look like this:
em.remove(em.contains(entity) ? entity : em.merge(entity));
In my case, I got the same error, when I tried to delete an object
using,
session.delete(obj)
without creating any transaction before that.
And the problem is solved by creating the transaction first(session.beginTransaction() and then deleting the object.
I hope my answer will help someone :)
Sometimes its simply because you are missing the #Transaction annotation for add, remove, update operations.
I faced the same problem. The detached entity should be re-attached. As #BalusC mentioned, using EntityManager.merge() should be used to attach the detached entity. EntityManager.merge() generates SQL Query which fetches the current state of the entity, on which EntityManager.remove() has to be performed. But in my case it didn't worked.
Try EntityManager.remove(EntityManager.find(Class<T>,arg)) instead. It worked for me.
In my experience, if I query an object from the DB then closed the entity manager then do a DB delete, the problem happens. Or if I copy that loaded object to another instance then do a delete, this problem also happens.
In my opinion there are 2 things to keep note:
The object must be in the same session that was created by the Entity Manager
And the object mustn't be transferred to another object while the Entity Manager's session is still opened.
Cheers

JPA EclipseLink Weaver generates call to porperty getter inside its setter -> NullPointerException

I have an #Embeddable class that uses property access to wrap another object that's not directly mappable by JPA via field access. It looks like this:
#Embeddable
#Access(AccessType.PROPERTY)
public class MyWrapper {
#NotNull
#Transient
private WrappedType wrappedField;
protected MyWrapper() {
}
public MyWrapper(WrappedType wrappedField) {
this.wrappedField = wrappedField;
}
#Transient
public WrappedType getWrappedField() {
return wrappedField;
}
public void setWrappedField(WrappedType wrappedField) {
this.wrappedField = wrappedField;
}
#Column(name = "wrappedTypeColumn")
protected String getJPARepresentation() {
return wrappedField.toString();
}
protected void setJPARepresentation(String jpaRepresentation) {
wrappedField = new WrappedType(jpaRepresentation);
}
}
Persisting an #Entity with a MyWrapper field works fine. But when I execute a query to load the Entity from the database, I get a NullPointerException. The stacktrace and some debugging shows that Eclipselink creates a new instance of MyWrapper by calling its default constructor and then calls the setJPARepresentation() method (as expected).
But now the unexpected happens: the stacktrace shows that the getJPARepresentation() is called from inside the setter, which then of course leads to a NullPointerException when return wrappedField.toString() is executed.
java.lang.NullPointerException
at MyWrapper.getJPARepresentation(MyWrapper.java:27)
at MyWrapper.setJPARepresentation(MyWrapper.java)
... 109 more
Fact is, there is obviously no call to the getter in the code and the stacktrace shows no line number indicating from where in the setter called the getter. So my conclusion would be, that the bytecode weaver of Eclipselink generated the call to the getter.
It's easy to build a workaround, but my question is: Why does Eclipselink do that?
P.S: I'm using EclipseLink 2.3.2.v20111125-r10461 in a GlassFish Server Open Source Edition 3.1.2 (build 23)
When weaving is enabled (default on Glassfish), EclipseLink will weave code into property get/set methods for,
change tracking
fetch groups (partial objects)
lazy (relationships)
For change tracking support the set method will be weaved to check if the new value is different than the old value, so it must call the get method to get the old value.
Now this is still odd, as since your are building a new object, I would not expect the change listener to be set yet, so would expect the change tracking check to be bypassed. You could decompile the code to see exactly what was generated.
The easiest fix is to just put in a null check in your get method, which is probably best in general for your code. You could also switch to field access, which will not have issues with side-affects in get/set methods. You could also use a Converter to handle the conversion, instead of doing the conversion in get/set methods.