How can I stop Hibernate EventListeners? - java

Here I am using hibernate 4.0.1.Final,
For Example,
class MyClassListener extends DefaultPreLoadEventListener
{
#Override
public void onPreLoad(PreLoadEvent event)
{
<!-- do something -->
}
}
Hibernate EventListener Structure is,
1. pre ---> after completed,
2. run ---> want to stop this default listener.
3. post ---> This also no need.
In my Hibernate Service class, when I call entityManager.find(Employee.class, empId);
Before that MyClassListener will call. After Completing this listener process, I want to stop the Hibernate find method Listener. How it is possible? any one help me.

Following the documentation at the hibernate site
I believe all you need to do is to set this property:
javax.persistence.validation.mode = "none"

Related

understanding #EntityListener behavior during a #Transactional test

I have an EntityListener that has a #PrePersist & #PreUpdate method (which simply logs the call). I created a test method where I save(entity). That will fire the listener method. However, when I annotate the test method with #Transactional (so that the changes to entity are rolled back after the test), my listener method does not fire. I also tried saveAndFlush(entity), but that did not work either. I expected the console log to be written to as soon as the entity was saved. Is that a correct assumption or am I not understanding how transactions are implemented?
Like any listener, you will need to register the event to be triggered using the bukkit event system. Here's an example from a bukkit thread
PluginManager pm = pl.getServer().getPluginManager();
pm.registerEvent(Event.Type.FOOD_LEVEL_CHANGE, new EntityListener(){
public void onFoodLevelChange(FoodLevelChangeEvent event){
// code
}
}, Event.Priority.Normal, this);

Spring JPA: Change attribute of instance that is simultaniously being modified in scheduled task

I'm running a scheduled task in my Spring application that runs a job. The job itself is fetched at the beginning of the task. After that a loop takes place that modifies the job in each iteration (++ a counter). After the loop I merge my instance using the entity manager. It works fairly well, but I'm facing an issue trying to modify the instance from another place. Since the instance has a 'paused' flag, I'm trying to set it. But whenever I do it's quickly reset again, due to the scheduled task unsetting it again (as far as I can tell).
Here's some code:
// This method is called using the #Scheduled annotation to be looping
// constantly with one second delay between invocations.
#Transactional
public void performActions() {
Job job = jobRepository.findFirstByPausedAtIsNull();
// Skip if no unpaused job exists
if(job == null) return;
// Iterate through batch of job actions
for(Action action : job.nextActions()) {
action.perform();
job.increaseActionsPerformedCount();
// Merge the action into the persistence context
entityManager.merge(action);
}
// Merge the job into the persistence context
entityManager.merge(job);
}
Now I'm trying to be able to pause the job at any time from the outside. I use a controller endpoint to call a pause method on the jobService. This method looks like this:
public Job pause(long id) throws JobNotFoundException, JobStatusException {
Job job = this.show(id);
if(job.getPausedAt() != null) throw new JobStatusException("The job is already paused");
job.pause(); // This sets the flag on the instance, same as job.setPausedAt(new Date())
return jobRepository.save(campaign); // Uses CrudRepository
}
Now calling the method works fine and it actually returns the Job with pausedAt set. But the value is reset quickly after.
I've tried just straight up fetching a fresh instance from the database at the end of performAction and setting the modified instance pausedAt to the freshly fetched one's value.
Any idea how this could be achieved properly?
As far as I understand , You need to stop the job when the pause flag is set ... you can achieve this by applying optimistic lock ... add a #Version field to Job .... apply LockModeType.OPTIMISTIC to the job that you retrieved in performAction() -either by adding it to the find() method or call a refresh() after retrieval -the first is better- ..... now if the other endpoint changes the pause flag the version field will be incremented and you will get OptimisticLockException at persisting .... this has some implications :
1- whatever state changes in the Job , the same behavior will happen (not only the pause field)
2- You will need to handle the Exception from inside the persistence context (i.e. inside performActions()) because after returning it might be mapped to any other exception type ... this is the idea I have now, may be there is something better that gives you more control (track only the pause attribute)

Update the Task model - RuntimeException: DataSource user is null?

I started learning Play framework today and it is very good and easy to learn.
I successfully completed the sample provided on their website, but I wanted to make some modifications to it.
I wanted to see if could update the label of a particular task, so I followed the following approach
First I added a route to update the data
POST /tasks/:id/update controllers.Application.updateTask(id: Long)
Then I added the following code to index.scala.html file
#form(routes.Application.updateTask(task.id)) {
<label class="contactLabel">Update note here:</label>
#inputText(taskForm("label")) <br />
}
Then I modified Application.java class to
public static Result updateTask(Long id) {
Form<Task> taskForm = Form.form(Task.class).bindFromRequest();
if (taskForm.hasErrors()) {
return badRequest(views.html.index.render(Task.all(), taskForm));
} else {
Task.update(id, taskForm.get());
return redirect(routes.Application.tasks());
}
}
Finally in Task.java I added this code
public static void update(Long id, Task task) {
find.ref(id).update(task.label);
}
But when I perform the update operation I get this error
[RuntimeException: DataSource user is null?]
Needless to say that I commented out
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"
ebean.default="models.*"
in application.conf since I am already able to save and delete data; but I cannot update the data in the database, why is this happening, did someone try this before, how can I solve this error?
Your update(Long id, Task task) method on Task model should be like below:
public static void update(Long id, Task task) {
task.update(id); // updates this entity, by specifying the entity ID
}
Because you passed task variable as updated data, you don't need to find reference of Task object like you do in find.ref(id). And moreover, update() method on play.db.ebean.Model class (with one parameter) needs ID of model as parameter.
Hope this help solving your problem.. :)
Ensure you have commented out Ebean configuration in application.conf
# Ebean configuration
# ~~~~~
# You can declare as many Ebean servers as you want.
# By convention, the default server is named `default`
#
ebean.default="models.*"

Spring Transaction Annotations - get active transaction

In my Spring application I have service-layer methods marked as #Transactional(propagation=Propagation.REQUIRED) and am using <tx:annotation-driven />. Normally the default behavior of automatically committing the transaction when the method completes works like a charm. But in the particular case, I need to commit shortly before the end of the method - yes, even if the parts that come after that point throw an exception.
Is there a way inside such a method to get access to the current transaction? I tried this:
TransactionDefinition td = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_MANDATORY); // make sure we're talking about the same transaction already provided by the annotation
TransactionStatus status = transactionManager.getTransaction(td);
// perform various JDBC operations
transactionManager.commit(status);
methodThatNeedsToBeCalledAfterCommit();
But looking through my logs, I only see "AbstractPlatformTransactionManager.processCommit(752) | Initiating transaction commit" occurring once, and from the timestamps this appears to be after methodThatNeedsToBeCalledAfterCommit(), which would be the normal behavior for #Transactional methods.
Is there a way to actually force a commit inside such a method?
I don't think so. Moreover, Spring will try to recommit at the end of your method.
So 2 commits : bad.
You should rethink the organization of your methods.
Maybe divide the existing one in 2 methods : one with #Trnasactional, the other with your remaining lines.
This is probably because the default transaction propagation is PROPAGATION_REQUIRED, and so will commit only when the entire transaction is completed - which is the outer method for you. You can try with PROPAGATION_REQUIRES_NEW:
td.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
Another alternative would be to use TransactionTemplate
Try this call this method from the program where you want to apply transaction.
DefaultTransactionDefinition transdefinition = new DefaultTransactionDefinition();
PlatformTransactionManager manager =new PlatformTransactionManager();
TransactionStatus status=null;
public void beginTransaction()
{
transdefinition.setPropagationBehavior(0);
status = manager.getTransaction(transdefinition);
}
public void commitTransaction()
{
if(status.isCompleted()){
manager.commit(status);
}
}
public void rollbackTransaction()
{
if(!status.isCompleted()){
manager.rollback(status);
}
}

How to wrap Wicket page rendering in a Spring / Hibernate transaction?

My application loads entities from a Hibernate DAO, with OpenSessionInViewFilter to allow rendering.
In some cases I want to make a minor change to a field -
Long orderId ...
link = new Link("cancel") {
#Override public void onClick() {
Order order = orderDAO.load(orderId);
order.setCancelledTime(timeSource.getCurrentTime());
};
but such a change is not persisted, as the OSIV doesn't flush.
It seems a real shame to have to call orderDOA.save(order) in these cases, but I don't want to go as far as changing the FlushMode on the OSIV.
Has anyone found any way of declaring a 'request handling' (such as onClick) as requiring a transaction?
Ideally I suppose the transaction would be started early in the request cycle, and committed by the OSIV, so that all logic and rendering would take place in same transaction.
I generally prefer to use additional 'service' layer of code that wraps basic DAO
logic and provides transactions via #Transactional. That gives me better separation of presentation vs business logic and is
easier to test.
But since you already use OSIV may be you can just put some AOP interceptor around your code
and have it do flush()?
Disclaimer : I've never actually tried this, but I think it would work. This also may be a little bit more code than you want to write. Finally, I'm assuming that your WebApplication subclasses SpringWebApplication. Are you with me so far?
The plan is to tell Spring that we want to run the statements of you onClick method in a transaction. In order to do that, we have to do three things.
Step 1 : inject the PlatformTransactionManager into your WebPage:
#SpringBean
private PlatformTransactionManager platformTransactionManager;
Step 2 : create a static TransactionDefinition in your WebPage that we will later reference:
protected static final TransactionDefinition TRANSACTION_DEFINITION;
static {
TRANSACTION_DEFINITION = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
((DefaultTransactionDefinition) TRANSACTION_DEFINITION).setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
}
Feel free to change the TransactionDefinition settings and/or move the definition to a shared location as appropriate. This particular definition instructs Spring to start a new transaction even if there's already one started and to use the maximum transaction isolation level.
Step 3 : add transaction management to the onClick method:
link = new Link("cancel") {
#Override
public void onClick() {
new TransactionTemplate(platformTransactionManager, TRANSACTION_DEFINITION).execute(new TransactionCallback() {
#Override
public Object doInTransaction(TransactionStatus status) {
Order order = orderDAO.load(orderId);
order.setCancelledTime(timeSource.getCurrentTime());
}
}
}
};
And that should do the trick!

Categories

Resources