I'm using a ajax4jsf poller <a4j:poll> to check whether an entity has been updated in the database by another process. I want to reload the entity each time.
How can I force a reload?
Calling loadInstance() seems to have has no effect. (Polling works as expected)
#Name("myComponentHome")
public class MyComponentHome extends EntityHome<ComponentType> {
public void poll() {
log.warn("poll");
ComponentType loadInstance = loadInstance();
if ( loadInstance.getReportTime() != null ) {
log.warn("poll report detected stoping poller");
setInstance( loadInstance() );
pollEnabled = false;
}
}
...
}
Versions Seam 2.1.2 Jboss 4.2
EDIT:
Maybe it's easier to answer if one knows that Seams loadInstance() is implemented as:
return getEntityManager().find(getEntityClass(), getId());
getEntityManager().refresh(entity);
Related
When we use a Flowable to get an update notification after inserting a new data-base row, works fine.
But when the insertion is done inside another explicit transaction, the Flowable does not get a notification.
To illustrate the issue, I've forked the BasicRxJavaSample from android-architecture-components and added 2 test-methods to UserDaoTest.java
#Test
public void testFlowable() {
// When subscribing to the emissions of the user
final TestSubscriber<User> userTestSubscriber = mDatabase.userDao().getUser().test();
userTestSubscriber.assertValueCount(0);
// When inserting a new user in the data source
mDatabase.userDao().insertUser(USER);
userTestSubscriber.assertValueCount(1);
}
This works fine. But when I do the same inside of an explicit transaction it does not work:
#Test
public void testFlowableInTransaction() {
// When subscribing to the emissions of the user
final TestSubscriber<User> userTestSubscriber = mDatabase.userDao().getUser().test();
userTestSubscriber.assertValueCount(0);
// When inserting a new user in the data source
mDatabase.beginTransaction();
try {
mDatabase.userDao().insertUser(USER);
mDatabase.setTransactionSuccessful();
} finally {
mDatabase.endTransaction();
}
userTestSubscriber.assertValueCount(1);
// this fails - the userTestSubscriber is still empty!
}
Note: this example is of course simplified, just to illustrate the issue.
Here's the generated DaoImpl.insertUser():
public void insertUser(User user) {
__db.beginTransaction();
try {
__insertionAdapterOfUser.insert(user);
__db.setTransactionSuccessful();
} finally {
__db.endTransaction();
}
}
We can see that this code uses a transaction and also my test-code uses another transaction.
According to the SupportSQLiteDatabase-beginTransaction() docs, nesting transactions should be okay.
Is this maybe a room-bug?
The room version of this project is 1.0.0-alpha3, but I can also see this problem with version 1.0.0-alpha8 (in another project)
This was a bug in room: #65471397
I verified that the bug has been fixed with version 1.0.0-rc1
I recently stumbled into the next piece of Java EE6 code:
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void example(#Observes(during = TransactionPhase.AFTER_SUCCESS) final ExampleEvent exampleEvent) {
Is REQUIRES_NEW really needed?
I mean example method will always be called only after any previous transaction has ended successfully ( because of TransactionPhase.AFTER_SUCCESS).
Or am I missing something?
Your are only observing ExampleEvent, so your example()-Method will not be called by itself (based on the #TransactionAttribute) unless your do something like this:
#Inject
private Event<ExampleEvent> exampleEvent;
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void example(#Observes(during = TransactionPhase.AFTER_SUCCESS) final ExampleEvent exampleEvent) {
ExampleEvent event = new ExampleEvent();
exampleEvent.fire(event);
}
It makes sense to keep the #TransactionAttribute because the previous transaction just finished (AFTER_SUCCESS), so there is no current transaction therefore a new one is needed to be created. It can be possible that this would be done automatically (depending on the AS implementation) even without the annotation, but the result should be the same.
I have a Play Framework 2 application
I use play 2.2.2 built with Scala 2.10.3 (running Java 1.7.0_25).
I have a method that checks the object with his copy from secured table. If the object has been changed it will be replaced with the object from secured table.
But when I call save ebean does not update it:
[debug] c.a.e.s.p.DefaultPersister - Update skipped as bean is unchanged
public static <T> T findAndRestore(Class<T> clazz, Long id) throws Exception {
T securedObject = SecuredEntityUtils.getObjectFromSecuredTable(clazz, id);
T entity = Ebean.find(clazz, id);
if (securedObject != null) {
if (entity == null) {
Ebean.save(securedObject);
} else if (!entity.equals(securedObject)) {
Ebean.update(securedObject);
}
} else {
logger.warn("Not found securedObject for entity : " + entity.getClass());
}
return securedObject ;
}
Is there a way to force ebean to save/update entire object ?
I might be wrong but Ebean did not mark the entity as dirty since you did not called any setter on it. Maybe using Ebean.markAsDirty(entity) could solve your issue (I know this is a pretty old question but since I stumbled upon it, maybe my answer could help somebody)
Is there a better way to check/detect if entity was updated in db? The reason being is the system publishes any changes to an external webservice, we dont want to publish if there is no changes as the webservice is slow to respond (we want to keep the soap body light as we are posting variable text lenght).
My current approach is described below:
For a given entity:
public class Comment {
int id;
String text;
}
In my service class I will detect it like so:
public class CommentServiceImpl {
void saveList(List<Comment> comments) {
for(Comment c : comments) {
Comment existing = this.findById(c.id);
if (existing != null) {
boolean nochange = existing.getText().equals(c.getText());
if (nochange) {
//do nothing, we don't want to publish to external webservice
} else {
this.save(c);
externalWs.publish(c);
}
}
}
}
This is not an answer in JPA but, if u are using Oracle, DCN is a pretty good api. Check it:
http://docs.oracle.com/cd/E11882_01/java.112/e16548/dbchgnf.htm
I am not really sure where my problem lies, as I am experimenting in two areas that I don't have much experience with: JPA and Futures (using Play! Framework's Jobs and Promises).
I have the following bit of code, which I want to return a Meeting object, when one of the fields of this object has been given a value, by another thread from another HTTP request. Here is what I have:
Promise<Meeting> meetingPromise = new Job<Meeting> () {
#Override
public Meeting doJobWithResult() throws Exception {
Meeting meeting = Meeting.findById(id);
while (meeting.bbbMeetingId == null) {
Thread.sleep(1000);
meeting = meeting.refresh(); // I tried each of these
meeting = meeting.merge(); // lines but to no avail; I
meeting = Meeting.findById(id); // get the same result
}
return meeting;
}
}.now();
Meeting meeting = await(meetingPromise);
As I note in the comments, there are three lines in there, any one of which I think should allow me to refresh the contents of my object from the database. From the debugger, it seems that the many-to-one relationships are refreshed by these calls, but the single values are not.
My Meeting object extends Play! Framework's Model, and for convenience, here is the refresh method:
/**
* Refresh the entity state.
*/
public <T extends JPABase> T refresh() {
em().refresh(this);
return (T) this;
}
and the merge method:
/**
* Merge this object to obtain a managed entity (usefull when the object comes from the Cache).
*/
public <T extends JPABase> T merge() {
return (T) em().merge(this);
}
So, how can I refresh my model from the database?
So, I ended up cross-posting this question on the play-framework group, and I got an answer there. So, for the discussion, check out that thread.
In the interest of having the answer come up in a web search to anyone who has this problem in the future, here is what the code snippet that I pasted earlier looks like:
Promise<Meeting> meetingPromise = new Job<Meeting> () {
#Override
public Meeting doJobWithResult() throws Exception {
Meeting meeting = Meeting.findById(id);
while (meeting.bbbMeetingId == null) {
Thread.sleep(1000);
if (JPA.isInsideTransaction()) {
JPAPlugin.closeTx(false);
}
JPAPlugin.startTx(true);
meeting = Meeting.findById(id);
JPAPlugin.closeTx(false);
}
return meeting;
}
}.now();
Meeting meeting = await(meetingPromise);
I am not using the #NoTransaction annotation, because that messes up some other code that checks if the request is coming from a valid user.
I'm not sure about it but JPA transactions are managed automatically by Play in the request/controller context (the JPAPlugin opens a transaction before invocation and closes it after invocation).
But I'm not sure at all what happens within jobs and I don't think transactions are auto-managed (or it's a feature I don't know). So, is your entity attached to an entitymanager or still transient? Is there a transaction somewhere? I don't really know but it may explain some weird behavior if not...