I tried to use transaction chain instead of data broker to create all transactions for the runtime of the product but failed with indication that the chain does not exist anymore.
The question is if transaction chain can produce only limited number of transactions or the lifetime of the chain has some limit.
There's no limit to the number of transactions but if a single transaction fails then that fails the whole chain and renders it unusable. Hence the reason for passing in a TransactionChainListener. The javadocs provide the details.
Related
I am trying to create an API in Spring Boot using #Transactional annotation regarding bank fund transfer.
Now I want to know - if there are multiple calls to the same API at the same time, how to manage transaction between them. Suppose for example transferBalance method is called by Transaction X which transfers funds from accounts A to B and another transaction Transaction Y transfer funds from B to C. Both transactions occur at the same time. How would these transactions be handled? What propagation should it have and also what about the isolation?
Check this below changes: for your case check bold description below.
if more than one transaction can also go with SERIALIZED
Isolation level defines how the changes made to some data repository by one transaction affect other simultaneous concurrent transactions, and also how and when that changed data becomes available to other transactions. When we define a transaction using the Spring framework we are also able to configure in which isolation level that same transaction will be executed.
#Transactional(isolation=Isolation.READ_COMMITTED)
public void someTransactionalMethod(Object obj) {
}
READ_UNCOMMITTED isolation level states that a transaction may read data that is still uncommitted by other transactions.
READ_COMMITTED isolation level states that a transaction can't read data that is not yet committed by other transactions.
REPEATABLE_READ isolation level states that if a transaction reads one record from the database multiple times the result of all those reading operations must always be the same.
SERIALIZABLE isolation level is the most restrictive of all isolation levels. Transactions are executed with locking at all levels (read, range and write locking) so they appear as if they were executed in a serialized way.
Your doubt has nothing to do with #Transactional.
Its simple question of concurrency.
Actually both the transaction, form a to b and form b to c can work concurrently.
By putting #Transactional states something like
works out whether a given exception should cause transaction rollback by applying a number of rollback rules, both positive and negative. If no rules are relevant to the exception, it behaves like DefaultTransactionAttribute (rolling back on runtime exceptions).
I am beginner to spring , now in my project we have method to make booking ,now if the available booking is 1 , when two user are trying booking at same time ideally only one booking is allowed , but my application is allowing two bookings, now i made the method as synchronized now it is working fine, but synchronization concept belongs to JVM now if I am configuring my application in cluster mode there are different servers in different machines(so different JVMS), now synchronization wont work.
Can any one please tell me the possible solution for this to restrict the booking,tell me solution from JAVA side and and also from DB side
If the application may be deployed in cluster, the synchronized method will indeed not be enough.
You should rely on a node shared by all server instances : the DB.
You could use DB locking features, especially optimistic locking and pessimistic locking.
With them, you could avoid collisions resulting from concurrent updates to the same line by concurrent clients.
Choose which one that matches better to your use case.
Concurrency control in databases extract:
Optimistic - Delay the checking of whether a transaction meets the
isolation and other integrity rules (e.g., serializability and
recoverability) until its end, without blocking any of its (read,
write) operations ("...and be optimistic about the rules being
met..."), and then abort a transaction to prevent the violation, if
the desired rules are to be violated upon its commit. An aborted
transaction is immediately restarted and re-executed, which incurs an
obvious overhead (versus executing it to the end only once). If not
too many transactions are aborted, then being optimistic is usually a
good strategy.
Pessimistic - Block an operation of a transaction, if
it may cause violation of the rules, until the possibility of
violation disappears. Blocking operations is typically involved with
performance reduction.
JDBC and JPA support both.
You should try with ETags - optimistic locking mechanism.
It can be easily implemented with Spring. Please check official documentation.
Hope this will help.
I am implementing a NiFi processor and have couple of clarifications to make with respect to best practices:
session.getProvenanceReporter().modify(...) - Should we emit the event immediately after every session.transfer()
session.commit() - Documentation says, after performing operations on flowfiles, either commit or rollback can be invoked.
Developer guide: https://nifi.apache.org/docs/nifi-docs/html/developer-guide.html#process_session
Question is, what do I lose by not invoking these methods explicitly?
1) Yes typically the provenance event is emitted after transferring the flow file.
2) It depends if you are extending AbstractProcessor, or AbstractSessionFactoryProcessor. AbstractProcessor will call commit or rollback for you so you don't need to, AbstractSessionFactoryProcessor requires you to call them appropriately.
If you are extending AbstractSessionFactoryProcessor and never call commit, eventually that session will get garbage collected and rollback will be called, and all the operations performed by that session will be rolled back.
There is also an annotation #SupportsBatching which can be placed on a processor. When this annotation is present, the UI shows a slider on the processor's scheduling tab that indicates how many milliseconds worth of framework operations like commit() can be batched together behind the scenes for increased throughput. If latency is more important then leaving the slides at 0 milliseconds is appropriate, but the key here is that the user gets to decide this when building the flow and configuring the processor.
There are various transaction propagations like
REQUIRED - This is the case for DML operation.
SUPPORTS - This is the case for querying database.
MANDATORY - ?
REQUIRES_NEW - ?
NOT_SUPPORTED - ?
NEVER - ?
NESTED - ?
What are some real life scenarios for these transaction propagations? Why these are perfect fit into that situation?
There are various usages and there is no simple answer but I'll try to be the most explainatory
MANDATORY (expecting transaction): Typically used when you expect that any "higher-context" layer started the transaction and you only want to continue in it. For example if you want one transaction for whole operation from HTTP request to response. Then you start transaction on JAX-RS resource level and lower layers (services) require transaction to run within (otherwise exception is thrown).
REQUIRES_NEW (always create new transaction): This creates a new transaction and suspends the current one if any exists. From above example, this is the level you set on your JAX-RS resource for example. Or generally if your flow somehow changes and you want to split your logic into multiple transactions (so your code have mutliple logic operations that should be separated).
REQUIRED (continue in transaction or create if needed): Some kind of mix between MANDATORY and REQUIRES_NEW. In MANDATORY you expect that the transaction exists, for this level you hope that it exists and if not, you create it. Typically used in DAO-like services (from my experience), but it really depends on logic of your app.
SUPPORTS (caller decides whether to not/run in transaction): Used if want to use the same context as caller (higher context), if your caller was running in transaction, then you run in too. If it didn't, you are also non-transactional. May also be used in DAO-like services if you want higher context to decide.
NESTED (sub-transaction): I must admit I didn't use this one in real code but generally you create a real sub-transaction that works as some kind of checkpoint. So it runs in the context of "parent" transaction but if it fails it returns to that checkpoint (start of nested transaction). This may be useful when you require this kind of logic in your application, for example if you want to insert large number of items to the database, commiting valid ones and keeping track of invalid ones (so you can catch exception when nested transaction fails but can still commit the whole transaction for valid ones)
NEVER (expecting there is no transaction): This is the case when you want to be sure that no transaction exists at all. If some code that runs in transaction reaches this code, exception is thrown. So typically this is for cases completely opposite to MANDARTORY. E.g. when you know that no transaction should be affected by this code - very likely because the transaction should not exist.
NOT_SUPPORTED (continue non-transactionally): This is weaker than NEVER, you want the code to be run non-transactionally. If somehow you enter this code from context where transaction is, you suspend this transaction and continue non-transactionally.
From my experience, you very often want one business action to be atomic. Thus you want only one transaction per request/... For example simple REST call via HTTP that does some DB operations all in one HTTP-like transaction. So my typical usage is REQUIRES_NEW on the top level (JAX-RS Resource) and MANDATORY on all lower level services that are injected to this resource (or even lower).
This may be useful for you. It describes how code behave with given propagation (caller->method)
REQUIRED: NONE->T1, T1->T1
REQUIRES_NEW: NONE->T1, T1->T2
MANDATORY: NONE->Exception, T1->T1
NOT_SUPPORTED: NONE->NONE, T1->NONE
SUPPORTS: NONE->NONE, T1->T1
NEVER: NONE->NONE, T1->Exception
Application server creates a new transaction before calling MDB's onMessage method. Also I am processing database update in onMessage method. Transactions create additional overhead and processing several message in one transaction could increase performance.
Is it possible to make App server to use one transaction for several messages. Or maybe there are other approaches to this problem?
And, by the way, I can't use multiple instances, cause I need to preserve the sequence order.
I guess you can store the messages in a list and depending upon how many messages you want to process in one transaction you can check the size of the list and process the messages.