i'v tried to make a lock on object but with no result
how to handle lock in this case ?
EDIT:
Based on comments I decided not to post question with code anymore. It's not about to copy and paste then run and check what compiler says.
Instead of focusing on the issue you create artificially a problem rather than face this one which I'm facing.
Instead of synchronized block maybe I should use the lock for writing or re entrant lock...
Do I required "hand-over-hand" or "chain locking"?
or even use semaphore?
EDIT2:
what i have:
i got object A which holds refrence to X and got method getX(return X) & resetX(X=null)
i got object X with fields a,b,c
what i do:
other thread T:
takes reference to X via _x = A.getX()
do some stuff change _x.a
do some stuff change _x.c
/// in meanwhile A decides to reset X ///
do some stuff change _x.b
... crash !
what i want to achieve:
prevent A.resetX(null) while T is modyfiing X(_x)
in other words to prevent object = null while there are modification to object in progress
do i need to use some flag indicating that X is under modification?
what i don't want:
constantly checks if(X!=null)
AND:
#downvoter: Care to explain your vote! please
OK! I've dug enough information to get solution for my case:
best way here is to use
interface ReadWriteLock provided by package java.util.concurrent.locks
together with implementation of:
ReentrantReadWriteLoc
here is "simple" sample example:
/**
* define modifiable dog
*/
public class Dog {
private ReadWriteLock _dogLock;
private String _name;
public Dog(ReadWriteLock dogLock) {
_dogLock = dogLock;
}
public Lock dogChangesLock() {
return _dogLock.writeLock();
}
public void setName(String name) {
_dogLock.writeLock().lock();
try {
_name = name;
} finally {
_dogLock.writeLock().unlock();
}
}
public String getName() {
_dogLock.readLock().lock();
try {
return _name;
} finally {
_dogLock.readLock().unlock();
}
}
}
/**
* holder class for dog handling
*/
public class Holder {
private Dog _dog;
/**
* EURECA! this is what we want to use
*/
private ReadWriteLock _dogLock = new ReentrantReadWriteLock();
/**
* get dog
*/
public Dog getDog() {
_dogLock.readLock().lock();
try {
if (_dog == null) {
_dog = new Dog(_dogLock);
}
return _dog;
} finally {
_dogLock.readLock().unlock();
}
}
/**
* utilize dog :)
*/
private void resetDog() {
_dogLock.readLock().lock();
try {
_dog = null;
} finally {
_dogLock.writeLock().unlock();
}
}
}
/**
* test class for simultaneous write/read
*/
public class Concurent {
Holder holder = new Holder();
/**
* run concurrent threads
*/
private void test() {
/** thread for dog modification */
new Thread(new Runnable() {
/** thread to utilize dog :) */
final Thread resetThread = new Thread(new Runnable() {
#Override
public void run() {
holder.resetDog();
}
});
/** main method */
#Override
public void run() {
/** get dog */
Dog dog = holder.getDog();
/** get lock for write */
dog.dogChangesLock().lock();
try {
/** modifies dog */
dog.setName("Cat");
/** call to reset dog */
resetThread.start();
/**
* SAFE TO CALL SECOND TIME
* we don't need to check if dog was altered
* as we got write lock
* */
dog.setName("Elephant");
} finally {
dog.dogChangesLock().unlock();
}
}
}).start();
}
}
Related
public Life(List<class> classes, int schoolwork) {
super(classes, schoolwork);
}
I am trying to make a Life object out of this code but am not doing it right what I have is
Life life = new Life();
but I can't figure out how to get the parameters right to include classes and schoolwork.
I tried to interpret your problem and I wrote a piece of code where I show you how to create a Life object by passing it the correct parameters.
Maybe your problem was creating the List object (?)
CODE
public class Main {
public static void main(String[] args) throws IOException {
List<CustomClass> customClass = new ArrayList<>();
int schoolwork = 1;
Life life = new Life(customClass, schoolwork);
}
}
class CustomClass {
}
class Life {
/**
* Constructor
*
* #param customClass
* #param schoolwork
*/
public Life(List<CustomClass> customClass, int schoolwork) {
// super(strings, schoolwork);
}
}
Background
I have an abstract class called Invoke
It can be instantiated as 2 separate classes that extend invoke: bigInvoke and smallInvoke.
I am trying to make an API that has an Invoke PUT request that allows the user to change the class of their invoke from big to small or vice versa.
My Code So Far
The BigInvoke.java looks like:
#NodeEntity
public class BigInvoke extends Invoke {
private String command;
public BigInvoke(){
this.invokeType = InvokeType.BigInvoke;
}
/**
* #return the command
*/
public String getCommand() {
return command;
}
/**
* #param command the command to set
*/
public void setCommand(String command) {
this.command = command;
}
}
And, in my invokeService.java I have:
#Override
public Invoke update(UUID uuid, Invoke invoke) {
Invoke i = find(uuid);
i.setInvokeType(invoke.getInvokeType());
invokeRepository.save(i);
return invoke;
}
Problem 1
But this just changes the value of the variable invokeType it doesn't actually change the class of the invoke.
How do I make this class change?
My Code for attempt #2
#Override
public Invoke update(UUID uuid, Invoke invoke) {
Invoke i = find(uuid);
UUID oldUUID = i.getUuid();
//make new one
Invoke newInvoke = new Invoke();
newInvoke.setInvokeType(invoke.getInvokeType());
//Delete old one
invokeRepository.deleteById(i.getUuid());
newInvoke.setUuid(oldUUID);
invokeRepository.save(newInvoke);
return newInvoke;
}
Problem with #2
This one works in the sense that the entity now has all the attributes that I want, but the deleteById deletes all the references to my Invoke. So my newInvoke no longer has the relationships of the older invoke. So, it doesn't really work.
Question
How do I change the class of my entity and keep all the relationships and the UUID?
Edit 1 SmallInvoke Code
#NodeEntity
public class SmallInvoke extends Invoke {
private String smallCode;
public SmallInvoke() {
this.invokeType = InvokeType.SmallInvoke;
}
/**
* #return the smallCode
*/
public String getSmallCode() {
return smallCode;
}
/**
* #param smallCode
* the smallCode to set
*/
public void setSmallCode(String smallCode) {
this.smallCode = smallCode;
}
}
EDIT 2 Info on InvokeRepository
InvokeRepository extends GenericRepository
GenericRepository extends Neo4jRepository
I am playing with functional programming and in particular with Functional Java. I have implemented with success my version of the IO Monad and I am writing IO actions for my core. It is basically serializing objects to Xml files (the object type extends the custom XmlWritable interface).
Unfortunately, in order to do that, an instance of OutputStream AND one instance of XmlSerializer needs to be created. The scope of the OutputStream is wider than XmlSerializer's, which means that the only way I can see to be able to correctly handle both lifecycles within my IO monad is to carry both of them with me in a tuple, closing OutputStream after having written using XmlSerializer.
This leads to heavy and ugly code (Java 6 is definitely not the best for this):
public abstract class IO<R> {
[...]
}
public class IOActions {
public final F<String, IO<OutputStream>> openFileFn() {
return new F<String, IO<OutputStream>>() {
#Override
public IO<OutputStream> f(String fileName) {
[...]
}
};
}
/* This will be partially applied, encoding will be fixed */
public static final F<OutputStream, IO<P2<OutputStream, XmlSerializer>>> initSerializer() {
return new F<OutputStream, IO<P2<OutputStream, XmlSerializer>>>() {
#Override
public IO<P2<OutputStream, XmlSerializer>> f(OutputStream os) {
XmlSerializer = new ...
[...]
}
};
}
/* This will be partially applied as well */
public static final F2<XmlWritable, P2<OutputStream, XmlSerializer>, IO<P2<OutputStream, XmlSerializer>>> writeObjectFn() {
return new F2<XmlWritable, P2<OutputStream, XmlSerializer>, IO<P2<OutputStream, XmlSerializer>>>() {
#Override
public IO<P2<OutputStream, XmlSerializer>> f(XmlWritable object, P2<OutputStream, XmlSerializer> p) {
[...]
}
};
}
Is there a more idiomatic why to handle my use case in functional programming?
Lurking, I discovered the State Monad...but I am kind of scared to see what it is going to happen if I apply a State Monad on top of a IO Monad in Functional Java.
I actually took great inspiration from Functional-Java's DB combinators to solve similar problems. I made my very own "XML combinators" (and more) from this pattern, so its worth learning.
You might find this discussion on google groups useful.
edit - replying to the comment:
follow the code:
notice how you start a new connection using the StateDb, see that you have a few options to start a connection, one that eventually commits, and one that eventually rollback. these are just two examples of things you can "carry" with the computation. Essentially, every computation that you bind (a plain modaic bind), could potentially carry information.
here is an example i gave in the discussion above:
DB<PreparedStatement> prepareStatement(final String sql) {
return new DB<PreparedStatement>() {
public PreparedStatement run(Connection c) throws SQLException {
return c.prepareStatement(sql);
}}}
// for a query that a reader might perform, i might have a function like this:
F<PreparedStatement, DB<ResultSet>> runStatement() {
public DB<ResultSet> f(final PreparedStatement s) {
return new DB<ResultSet>() {
public ResultSet run (Connection c) throws SQLException {
return s.executeQuery();
}}}
So in this example, you can pass extra information, namely the sql query as a parameter to the function that gets bound. you could just as well had more parameters to runStatement.
to put it all together, you get something like:
ResultSet rs = DbState.reader("conn-url").run(prepareStatement("select * from table").bind(runStatement());
Hope this helps!
Here is what I have come up with. Feedback is very appreciated.
I followed the answer above, taking inspiration from the linked discussion:
public class IOXml<T extends XmlWritable> implements DataWriter<T>{
private final XmlSerializer mXmlSerializer;
private final Option<String> mXmlEncoding;
private final IO<OutputStream> ioCreateStream;
private final F<OutputStream, IO<Unit>> ioCloseStream;
#Inject
IOXml(IO<OutputStream> createStream, F<OutputStream, IO<Unit>> closeStream, XmlSerializer xmlSerializer, Option<String> xmlEncoding) {
mXmlSerializer = xmlSerializer;
mXmlEncoding = xmlEncoding;
ioCreateStream = createStream;
ioCloseStream = closeStream;
}
/**
* Write a T object which is XmlWritable.
* #param osAndSer The tuple containing OutputStream and XmlSerializer.
* #param object The object to write.
* #return IO monad object.
*/
protected IO<Unit> writeObject(final T object) {
return new IO<Unit>() {
#Override
public Unit performIO() throws IOException {
object.writeXml(mXmlSerializer);
return Unit.unit();
}
};
}
protected final F<Unit, IO<Unit>> writeObjectFn(final T object) {
return new F<Unit, IO<Unit>>() {
#Override
public IO<Unit> f(Unit a) {
return writeObject(object);
}
};
}
/**
* Initialize the XmlSerializer before using it.
* #param os An OutputStream.
* #param encoding The encoding of the xml file.
* #return An IO action returning nothing.
*/
protected IO<Unit> initXml(final OutputStream os) {
return new IO<Unit>() {
#Override
public Unit performIO() throws IOException {
mXmlSerializer.setOutput(os, mXmlEncoding.toNull());
mXmlSerializer.startDocument(mXmlEncoding.toNull(), true);
return Unit.unit();
}
};
}
/**
* Close the XmlSerializer after.
* #return An IO action returning nothing.
*/
protected IO<Unit> closeXml() {
return new IO<Unit>() {
#Override
public Unit performIO() throws IOException {
mXmlSerializer.endDocument();
return Unit.unit();
}
};
}
protected final F<Unit, IO<Unit>> closeXmlFn() {
return new F<Unit, IO<Unit>>() {
#Override
public IO<Unit> f(Unit a) {
return closeXml();
}
};
}
#Override
public void close() throws IOException {
closeXml().performIO();
}
#Override
public void write(T object) {
throw new UnsupportedOperationException("Are you sure? IOXml is a functional class. Use the function returned by liftIO instead.");
}
/**
* Curried function to write XML objects, given the object itself and an OutputStream.
* #return The curried function.
*/
protected F<OutputStream, F<T, IO<Unit>>> writeFn() {
// returning the outer
return new F<OutputStream, F<T, IO<Unit>>>() {
#Override
public F<T, IO<Unit>> f(final OutputStream os) {
// Returning the inner
return new F<T, IO<Unit>>() {
#Override
public IO<Unit> f(T object) {
return initXml(os).bind(writeObjectFn(object)).bind(closeXmlFn());
}
};
}
};
}
#Override
public IO<Unit> writeIO(final T object) {
return IOImpl.bracket(ioCreateStream, // init
ioCloseStream, // close
Function.partialApply2(writeFn(), object)); // body
}
}
My question is: How do I access values from another thread?
I have two .java files, Main.java and TrackHands.java
Main.java
/**
* This is the main class, it is used to start the program. The only use of this
* is to make everything more organized.
*/
package Kinect;
//import processing.core.PApplet;
/**
* #author Tony Nguyen <Tony.Nguyen#HvA.nl>
*
*/
public class Main
{
public static void main(String _args[])
{
Thread trackHands = new Thread(new TrackHands());
trackHands.start();
}
}
TrackHands.java
/*
* This uses the normal Java layout to track the user and prints out the coordinates of the left and right hand
*/
package Kinect;
import SimpleOpenNI.*;
import processing.core.PApplet;
import processing.core.PVector;
/**
* #author Tony Nguyen <Tony.Nguyen#HvA.nl>
* #version 1.0
*/
public class TrackHands extends PApplet implements Runnable
{
private int handLeftX, handLeftY = 0; // Holds the coordinates of the left hand
SimpleOpenNI kinect = new SimpleOpenNI(this); // kinect object
/**
* Constructor Takes no parameters
*/
public TrackHands()
{
}
/**
* run This will be executed when the thread starts
*/
#Override
public void run()
{
IntVector userList = new IntVector(); // Make a vector of ints to store the list of users
PVector leftHand = new PVector(); // Make a vector to store the left hand
PVector convertedLeftHand = new PVector();
kinect.enableDepth();
kinect.enableUser(SimpleOpenNI.SKEL_PROFILE_ALL);
kinect.setMirror(true);
while (true)
{
kinect.update();
kinect.getUsers(userList); // Write the list of detected users into the vector
if (userList.size() > 0) // Checks if a user is found
{
int userId = userList.get(0); // Get first user
if (kinect.isTrackingSkeleton(userId)) // If successfully calibrated
{
kinect.getJointPositionSkeleton(userId,
SimpleOpenNI.SKEL_LEFT_HAND, leftHand); // Put the position of the left hand into that vector
kinect.convertRealWorldToProjective(leftHand,
convertedLeftHand);
this.handLeftX = round(convertedLeftHand.x);
this.handLeftY = round(convertedLeftHand.y);
}
}
}
}
// User-tracking callbacks!
public void onNewUser(int userId)
{
System.out.println("Start pose detection");
kinect.startPoseDetection("Psi", userId);
}
public void onEndCalibration(int userId, boolean successful)
{
if (successful)
{
System.out.println(" User calibrated !!!");
kinect.startTrackingSkeleton(userId);
} else
{
System.out.println(" Failed to calibrate user !!!");
kinect.startPoseDetection("Psi", userId);
}
}
public void onStartPose(String pose, int userId)
{
System.out.println("Started pose for user");
kinect.stopPoseDetection(userId);
kinect.requestCalibrationSkeleton(userId, true);
}
}
I have tried to use a getter and a setter to get the values from TrackHands.java into another thread.
Tried creating objects and passing the values as parameters, but then my program will not use these new values in the run() method.
To get values from TrackHands, use a get method that accesses an instance variable that is set in run()
class TrackHands {
Object output;
public void run() {
while(true) {
output = new Object();
}
}
public Object getOutput() {
return output;
}
}
Pass TrackHands into your consumer object and use it to call get getOutput() method.
Passing values in is a bit trickier, because you might cause race condition. Try something like this
class TrackHands {
Object input = null;
public boolean setInput(Object input) {
if(this.input == null) {
this.input = input;
return true;
} else {
return false;
}
}
}
When your run() method uses input, set it to null so that another thread can pass in another input. Your producer thread will use this loop to pass in input:
public void sendInput(TrackHands th, Object input) {
boolean done = false;
while(!done) {
done = th.setInput(input);
}
}
This will keep trying to pass in input until it succeeds.
setInput uses the synchronized keyword so that only one thread can call this method at once, otherwise you'll get a race condition.
A friend of mine solved my problem.
I want to thank everyone for helping me!
Main.java
/**
* This is the main class, it is used to start the program. The only use of this
* is to make everything more organized.
*/
package Kinect;
//import processing.core.PApplet;
/**
* #author Tony Nguyen <Tony.Nguyen#HvA.nl>
*
*/
public class Main
{
public static void main(String _args[])
{
// PApplet.main(new String[]
// {
// Sensor.class.getName()
// });
ValueStore valueStore = new ValueStore(); // ADDED THIS LINE
Thread trackHands = new Thread(new TrackHands(valueStore)); // ADDED THIS LINE
trackHands.start();
}
}
TrackHands.java
/*
* This uses the normal Java layout to track the user and prints out the coordinates of the left and right hand
*/
package Kinect;
import SimpleOpenNI.*;
import processing.core.PApplet;
import processing.core.PVector;
/**
* #author Tony Nguyen <Tony.Nguyen#HvA.nl>
* #version 1.0
*/
public class TrackHands extends PApplet implements Runnable
{
private int handLeftX, handLeftY, handRightX, handRightY = 0; // Holds the coordinates of the left hand
SimpleOpenNI kinect = new SimpleOpenNI(this); // kinect object
private ValueStore valuesStore; // ADDED THIS LINE
/**
* Constructor Takes no parameters
*/
public TrackHands()
{
}
public TrackHands(ValueStore valuesStore)
{
this.valuesStore = valuesStore;
}
/**
* run This will be executed when the thread starts
*/
#Override
public void run()
{
IntVector userList = new IntVector(); // Make a vector of ints to store the list of users
PVector leftHand = new PVector(); // Make a vector to store the left hand
PVector rightHand = new PVector(); // Make a vector to store the right hand
PVector convertedLeftHand = new PVector(); // Make a vector to store the actual left hand
PVector convertedRightHand = new PVector(); // Make a vector to store the actual right hand
kinect.enableDepth();
kinect.enableUser(SimpleOpenNI.SKEL_PROFILE_ALL);
kinect.setMirror(true);
while (true)
{
kinect.update();
kinect.getUsers(userList); // Write the list of detected users into the vector
if (userList.size() > 0) // Checks if a user is found
{
int userId = userList.get(0); // Get first user
if (kinect.isTrackingSkeleton(userId)) // If successfully calibrated
{
kinect.getJointPositionSkeleton(userId,
SimpleOpenNI.SKEL_LEFT_HAND, leftHand); // Put the position of the left hand into that vector
kinect.getJointPositionSkeleton(userId,
SimpleOpenNI.SKEL_RIGHT_HAND, rightHand); // Put the position of the left hand into that vector
kinect.convertRealWorldToProjective(leftHand,
convertedLeftHand);
kinect.convertRealWorldToProjective(rightHand,
convertedRightHand);
this.handLeftX = round(convertedLeftHand.x);
this.handLeftY = round(convertedLeftHand.y);
this.handRightX = round(convertedRightHand.x);
this.handRightY = round(convertedRightHand.y);
valuesStore.setHandValues(handLeftX, handLeftY, handRightX, handRightY); // ADDED THIS LINE
}
}
}
}
// User-tracking callbacks!
public void onNewUser(int userId)
{
System.out.println("Start pose detection");
kinect.startPoseDetection("Psi", userId);
}
public void onEndCalibration(int userId, boolean successful)
{
if (successful)
{
System.out.println(" User calibrated !!!");
kinect.startTrackingSkeleton(userId);
} else
{
System.out.println(" Failed to calibrate user !!!");
kinect.startPoseDetection("Psi", userId);
}
}
public void onStartPose(String pose, int userId)
{
System.out.println("Started pose for user");
kinect.stopPoseDetection(userId);
kinect.requestCalibrationSkeleton(userId, true);
}
}
Then added a class to store the values so another class can access it.
ValueStore.java
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package Kinect;
/**
*
* #author Tony Nguyen <Tony.Nguyen#HvA.nl>
*/
public class ValueStore
{
private int leftX, leftY, rightX, rightY = 0;
public void setHandValues(int leftX, int leftY, int rightX, int rightY)
{
this.leftX = leftX;
this.leftY = leftY;
this.rightX = rightX;
this.rightY = rightY;
}
public int getLeftX()
{
return this.leftX;
}
}
I'm implementing a method that does something like:
...
try {
myPojo.setProperty("foo");
myService.execute(myPojo);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
...
If some exception is thrown by my service from this try block on pojo property will have the new value. Is there some way to start a kind of transaction for pojo changes and roll it back if something goes wrong?
Something like:
PojoTransaction pt = startPojoTransaction();
transactionedPojo = pt.handleByTransaction(myPojo);
try {
transactionedPojo.setProperty("foo");
myService.execute(transactionedPojo);
pt.commit;
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
Or something similar...
Take a look at the Memento Pattern, it includes a Java example.
http://en.wikipedia.org/wiki/Memento_pattern
I toyed around with the idea, this is far from perfect, just a simple proof of concept. There are pitfalls in this implementation:
It only tries to call a parameterless constructor of the given source
object to create the target-copy, would need some logic to select a correct constructor (or only support Cloneables?)
Only copies fields declared in the class, not from superclasses (this problem can be solved walking through the inheritance tree and copying any superclass fields)
If the fields are complex types, only the references are copied to target-object, so any changes to them will not be transactional, as both the source and target share the same instance (solvable by recursively creating copies of nested objects and copying their values, requires walking through the entire object-graph, starting from source, and then doing it vice-versa on commit-time)
But, improving from here, I believe it could become very usable. Here's the POC:
import java.lang.reflect.Field;
import org.junit.Assert;
import org.junit.Test;
public class PojoTransactionTest
{
public static class PojoTransaction<T>
{
/**
* This is the original (unmodified) object
*/
private T source;
/**
* This is the object modified by within the transaction
*/
private T target;
/**
* Creates a new transaction for the given source object
* #param source Source object to modify transactionally
*/
public PojoTransaction(T source)
{
try
{
this.source = source;
this.target = (T)source.getClass().newInstance(); //Note: this only supports parameterless constructors
copyState(source, target);
}
catch(Exception e)
{
throw new RuntimeException("Failed to create PojoTransaction", e);
}
}
/**
* Copies state (member fields) from object to another
* #param from Object to copy from
* #param to Object to copy to
* #throws IllegalAccessException
*/
private void copyState(T from, T to) throws IllegalAccessException
{
//Copy internal state to target, note that this will NOT copy fields from superclasses
for(Field f : from.getClass().getDeclaredFields())
{
f.setAccessible(true);
f.set(to, f.get(from));
}
}
/**
* Returns the transaction target object, this is the one you should modify during transaction
* #return Target object
*/
public T getTransactionTarget()
{
return target;
}
/**
* Copies the changes from target object back to original object
*/
public void commit()
{
try
{
copyState(target, source);
}
catch(Exception e)
{
throw new RuntimeException("Failed to change state of original object", e);
}
}
}
public static class TestData
{
private String strValue = "TEST";
private int intValue = 1;
private float floatValue = 3.1415f;
public String getStrValue()
{
return strValue;
}
public void setStrValue(String strValue)
{
this.strValue = strValue;
}
public int getIntValue()
{
return intValue;
}
public void setIntValue(int intValue)
{
this.intValue = intValue;
}
public float getFloatValue()
{
return floatValue;
}
public void setFloatValue(float floatValue)
{
this.floatValue = floatValue;
}
}
#Test
public void testTransaction()
{
//Create some test data
TestData orig = new TestData();
//Create transaction for the test data, get the "transaction target"-object from transaction
PojoTransaction<TestData> tx = new PojoTransaction<TestData>(orig);
TestData target = tx.getTransactionTarget();
target.setFloatValue(1.0f);
target.setIntValue(5);
target.setStrValue("Another string");
//Original object is still at the original values
Assert.assertEquals(1, orig.getIntValue());
Assert.assertEquals(3.1415f, orig.getFloatValue(), 0.001f);
Assert.assertEquals("TEST", orig.getStrValue());
//Commit transaction
tx.commit();
//The "orig"-object should now have the changes made to "transaction target"-object
Assert.assertEquals(5, orig.getIntValue());
Assert.assertEquals(1.0f, orig.getFloatValue(), 0.001f);
Assert.assertEquals("Another string", orig.getStrValue());
}
}
The question is a bit vague, but it sounds like you are wrestling with the basic design pattern for transaction management. You would benefit greatly from the experience that has gone into the production of the pattern used here:
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html
Perhaps Spring Transaction management would suit you well for your project anyway.