How to update database table when an exception occured in business logic - java

I have an api which is doing following process :-
Validating request
Saving the request in DB
Calling a different api synchronously to place the deal
Sending 201 response.
Currently if any exception is coming on step 3, we are catching it and doing following operations:-
try{
Step 3}
Catch(exception e){
Log
UpdateDbstate()
}
Where updatedb state method is updating db state and try catch again if any db exception occured.
Problem here is if any exception occured in updatedbstate, the whole transaction will now be in inconsistent state as db is not updated
How to correctly implement a solution around this.

I would suggest using #Transactional at service level, which would rollback the incomplete updates in db when any sql exceptions occur.
Example:
#Transactional(rollbackFor = { SQLException.class })
public ResponseEntity post() {
. . .
}
You can read further from this guide:
https://www.marcobehler.com/guides/spring-transaction-management-transactional-in-depth

Related

AWS Causes in Dyanmo for ConditionalCheckFailedException?

I have about 30 instances running and submitting data to dynamo, but in my logs, I'm getting a ton of ConditionalCheckFailedException failure messages. The weird thing is, I'm not saving with any conditional check, unless I'm missing something:
private void save(DynamoObject myObject) {
try {
mapper.save(model);
} catch (ConditionalCheckFailedException e) {
// metrics and logging
} catch (Exception e) {
// metrics and logging
}
What could be causing this?
It looks like you are using DynamoDBMapper and specifically #DynamoDBVersionAttribute somewhere and your put item failure is related to the mapper's optimistic locking strategy. The item version on the server is different to that on the client side because of another write to that item, so DynamoDB rejects the put.
You'll need to reconcile the item differences client-side and re-submit.

What rollback actually does?

I trying to find out what rollback actually does.
I have couple of scenarios:
Rolling back after a successful commit.
Connection conn=getConnection();
try{
executesSomeQuery(conn);
conn.commit();
} catch(Exception e){
//assume no exception
}finally{
conn.rollback();
}
Rolling back after an unsuccessful commit. If committing three queries q1, q2, q3 in order within the same commit(), what happens to q1 if q2 fails? and how conn.rollback() helps? Will the conn.commit() rollback without the need of rollback()?
Connection conn=getConnection();
try{
executesSomeQuery(conn); // has three queries in order; q1, q2, q3. q2 fails and causes error
conn.commit();
} catch(Exception e){
//assume exception is thrown because commit failed due to q2
conn.rollback();
}
As the name suggests, rollback() rolls back transaction and does not make any change to the database.
All the statements in your try block get executed sequentially on DB. If any of them throws an exception the code does not commit the changes, instead, it reverts them all and leaves the DB in the unimpacted state.
This helps to achieve Atomicity for multiple transactions.
Commit and rollback inform the database to commit or rollback (i.e. undo) the current transaction. At the Java level, they don't actually do much at all.
How it's done on the database varies on the actual database implementation.
In your case, if q2 fails, whatever effects q1 had on the database will be undone.
And, naturally, q3 won't be executed at all.
The idea of the rollback is that, whenever you are inserting/updating data in the database, if there are any errors rollback will save you from inserting/updating wrong/not complete data into the database. By looking at your code snippet 1- is wrong, you should rollback in the catch, if the error is caught than rollback must happen, finally is last in execution so by that time data is already committed, there is nothing to rollback.

how to acknowledge delete method of morphia (Monogo DB)

I morphia datastore there i a delete method.
this method is working fine.
but i have doubt about it is
how we can get the information about the method delete the data successfully.
since the delete() method return WriteResult and in WriteResult which method we have to use so as to we can say data has been delete.
In my case i am using rest web service and in rest web service we have to send http responses like 200,400,500 etc.
while using delete method i should have to get information about the data is really deleted.
how we can achieve this task.
example
int deleteMongoObject(MognoDataObject mongoDataObject) {
Datastore datastore=MorphiaDatastoreTrasaction.getDatastore(MognoDataObject.class);
datastore.delete(mongoDataObject);
if(scuccess) {\\ success should be acknowledgment of delete method
return 200;
}
else {
retrun 403;
}
}
how we can achieve this task
delete() returns a WriteResult that shows the number of documents affected. The n field should list the number of documents deleted.
Also as you can see in Morphia Datastore implementation default WriteConcern is ACKNOWLEDGED unless you specified something else for example annotation under your model.
And description of ACKNOWLEDGED:
Write operations that use this write concern will wait for
acknowledgement from the primary server before returning. Exceptions
are raised for network issues, and server errors.

Getting unreachable statement error even though it reaches during run time in spring hibernate

I am trying to catch exceptions which will occur during run time in spring hibernate below is hibernate code which inserts data into sql table but i want to catch certain exceptions but i am getting below
error:
Unreachable catch block for JDBCConnectionException.
This exception is never thrown from the try statement body
try
{
TokenBo tokenBo = (TokenBo)appContext.getBean("TokenBo");
Token token = new Token();
token.setFirstName(FirstName);
tokenBo.save(token);
}
catch(JDBCConnectionException e1) {}
Runtime Exception & Error are supposed to happen at run time (reporting that something went wrong when the program ran) and ConstraintViolationException is a runtime exception
The error you are getting is because ConstraintViolationException is never thrown from your code.
Why would you even want to catch ConstraintViolationException? This exception states that you failed to fulfill one of the DB constraints, which means you didn't have proper data check in place
To avoid "chat" mode in commens:
The error message is pretty self-explanatory:
This exception is never thrown from the try statement body
Remove the catch block for the ConstraintViolationException. Don't try to handle Exceptions that can not be thrown by your code.
If you remove this, and running your code causes a JDBCConnectionException, you'll need to tackle this problem, not creating another one to hide it.
If you need help to fix that issue, you'll have to provide more code/configuration/stacktrace/...

Hibernate Delayed Write

I am wondering if there is a possibility of hibernate delaying its writes to the DB. I have hibernate configured for mysql. Scenarios I hope to support are 80% reads and 20% writes. So I do not want to optimize my writes, I rather have the client wait until the DB has been written to, than to return a bit earlier. My tests currently have 100 client in parallel, the cpu does sometimes max out. I need this flush method to write to DB immediately and return only when the data is written.
On my client side, I send a write request and then a read request, but the read request sometimes returns null. I suspect hibernate is not writing to db immediately.
public final ThreadLocal session = new ThreadLocal();
public Session currentSession() {
Session s = (Session) session.get();
// Open a new Session, if this thread has none yet
if (s == null || !s.isOpen()) {
s = sessionFactory.openSession();
// Store it in the ThreadLocal variable
session.set(s);
}
return s;
}
public synchronized void flush(Object dataStore) throws DidNotSaveRequestSomeRandomError {
Transaction txD;
Session session;
session = currentSession();
txD = session.beginTransaction();
session.save(dataStore);
try {
txD.commit();
} catch (ConstraintViolationException e) {
e.printStackTrace();
throw new DidNotSaveRequestSomeRandomError(dataStore, feedbackManager);
} catch (TransactionException e) {
log.debug("txD state isActive" + txD.isActive() + " txD is participating" + txD.isParticipating());
log.debug(e);
} finally {
// session.flush();
txD = null;
session.close();
}
// mySession.clear();
}
#Siddharth Hibernate does not really delay in writing the response , and your code also does not speaks the same. I have also faced similar issue earlier and doubt you might be facing the same that is , when there a numerous request for write into hibernate are there many threads share same instance of your db and even having consecutive commits by hibernate you really dont see any changes .
You may also catch this by simple looking at you MySQL logs during the transaction and see what exactly went wrong !
Thanks for your hint. Took me some time to debug. Mysql logs are amazing.
This is what I run to check the time stamp on my inserts and mysql writes. mysql logs all db operations in a binlog. To read it we need to use the tool called mysqlbinlog. my.cnf too needs to be http://publib.boulder.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom.ibm.ztpf-ztpfdf.doc_put.cur%2Fgtpm7%2Fm7enablelogs.html
I check which is the lastest mysql bin log file, and run this to grep for 1 line above the log, to get the time stamp. Then in java, I call Calendar.getInstance().getTimeInMilli() to compare with the time stamp.
sudo mysqlbinlog mysql/mysql-bin.000004 | grep "mystring" -1
So I debugged my problem. It was a delayed write problem. So I implemented a sync write too instead of all async. In other words the server call wont return until db is flushed for this object.

Categories