We have a Spring based application with a service layer which is annotated with #Transactional. We need to have code run before and after some transactional methods for the following reasons:
We need to synchronize access to the method based on a key. The thread needs to block before the start of the transaction.
We need to post a message on a queue if the transaction succeeds.
The options seem to be:
Create a class with similar methods to the service that can run the #Transactional method in a synchronized block and check for the return then post the message (would need a separate class due to AOP proxy problem). Services calling services, not nice, feels like a work-around.
Write an aspect to wrap around the #Transactional AOP which can do the synchronization and message posting. Might work but would rather avoid AOP.
Move the transaction down to the domain layer. Not desirable or possibly even feasible with the current implementation due to the way domain methods are reused in different workflows.
Code the transaction by hand in the service method and scrap #Transactional.
I would imagine this is a fairly common requirement. Probably I am missing an option 5, which is the obvious one!
I think I'd go with 2 unless you have some specific reasons to avoid AOP. Your problem is a classic example of where AOP can be used and it looks pretty good in the result. Here is a nice example of how to implement that (if you didn't read that already): Advising transactional operations
If AOP is really not an option, I'd go the 'Otherwise' option proposed by #Lawrence McAlpin.
Check out TransactionSynchronization callback interface. Spring can natively inform you what is happening with your transaction.
I would use a TransactionTemplate (your option 4) and programatically control the scope of the transaction in situations like this.
Otherwise, you could move the logic in your method out into a separate service, make that new service #Transactional, remove the #Transactional from the current method, and then surround the call to the new service with your pre- and post-transaction logic. I've taken this approach as well, but I prefer programmatic transaction management for requirements like this, as I think it's cleaner and, as you mentioned, services calling services (that are only ever needed by the first service) just feels like a hackish workaround.
if the key is being passed as part of the method call, then you can use java ReentrantLock to do the job.. its much simpler & cleaner.
Related
we have this code where the same service method will call different daos each using a different datasource (and different JdbcTemplates). We would like to use #Transactional annotation, but as far as I know, this annotation is always linked to a specific TransactionManager (and thus, to a specific DataSource).
So, my question is, is there a way to choose dynamically which DataSource (or TransactionManager) using when calling a #Transactional method so I can reuse that method to attack different databases?
The #Transactional annotation doesn't allow dynamic evaluation of the value attribute which selects the TransactionManager (possibly by design, at least it doesn't look like it's going to change any time soon). So you can't have something like #Transactional("#{#getTxManager}") which would resolve the tx manager at call time.
In simple cases you might be able to get away with the following, but it would only be worth considering when for example you have a primary DS, and a secondary DS that's used only in some cases. Otherwise you'd be peppering the code that selects between calling foo/bar all around, and that wouldn't look clean at all
// TX boundary on the "top" abstraction layer
#Transactional("foo")
public void foo() {
doWork();
}
#Transactional("bar")
public void bar() {
doWork();
}
private void doWork() {
// Work done here, no concern for tx management
}
For more complex cases like multitenancy, AbstractRoutingDataSource is an easy and robust choice if you haven't considered it yet. Although depending on how much switching you need, it may require tweaking or be even unsuitable.
Finally, you might be able to create your own annotation that does choose the DS dynamically (although I don't guarantee it), but that would be the riskiest approach for possible very little gains.
The safest way for you would be to create separate services for each dao... I wouldn't like to be debugging such code. Think about maintaining this code and possible failures that might happen.
If I were you I'd ask myself following questions:
1.) Why separate dbs?
2.) Isn't the context somehow mixed up? Maybe create some boundaries between them?
3.) Do my queries really need to be transactional?
I probably don't know the context of your problem but for me it seems that you've modeled your application in a wrong way and I'd focus on it.
The background: there is a requirement to attach auditing data to persisted entities, basically creation-timestamp + user ID and last-update-timestamp + user ID.
I'm not keen on passing the user ID as a method parameter through all layers/components. So I need to somehow pass user identifcation (derived from HTTP headers, the details are unimportant) through a REST endpoint (using RESTEasy, but that's probably not important, either) back to the data access/repository layer.
I've thought of using ThreadLocal but it feels a little hackish and might fail in a non-blocking IO environment. Maybe I'm wrong about that, not sure.
I also have a vague idea that AOP could help, though I'm not well-versed in AOP so not sure.
Any strategies appreciated, with or without code.
You can use entity lifecycle callback methods for your requirement: #PrePersist, #PostPersist, #PreUpdate, #PostUpdate.
It is one of the auditing strategies mentioned here.
It turns out that Spring's SecurityContextHolder is a reasonable place to do this (don't ask why the application isn't already integrating "properly" with Spring Security). It's basically the ThreadLocal option but with some nice interface around it.
The tradeoff is that you need to be acutely aware of the thread-bound nature of this solution. A controller that somehow uses other thread to do the work that needs the user context, will need to take some steps to make sure those threads can get it since they don't, by default, inherit the ThreadLocal. There is a mode you can set on SecurityContextHolder that will use inheritance of the ThreadLocal in any newly created threads, but that does not help if a thread pool is used (since threads won't be created by the request thread but rather pulled from the pool). Even then, most thread pools provide a way for the client thread to do "something" when obtaining and releasing threads, so it's possible to pass the security context on that way.
I wanted to make it clear for me.
I read about AOP concept and I understood that it's a great way to share cross cutting services. (logging, security, transaction...)
But I would like to say/ask something about this idea and it's implementation.
I read there are some ways like AspectJ, JBOSS AOP in order to assimilation AOP to my business logic.
but wasnt it here already long time ago?
let's say for example I want to share a logging or security implementation amongs my components(Java beans, EJB'S, whatsoever.. )
Why couldn't I make a Singleton bean making sure it will has only one instance and as soon as any component will need it's logging/security service it would look-up and use it's service.
Why would I need to understand and have all those "Big" implementations such as aspectj or jboss AOP? What do I miss here?
The idea of AOP is to keep common logic in one place (which your singleton solution solves as well) and being "invisible" (transparent). With AOP your logging code isn't even part of the business logic, it is "injected" behind the scenes.
Also it is more dynamic - you don't need to call your singleton service every time you need logging. Just configure a pointcut once (like: "all setters in this package") and logging will be applied for all existing and new code.
Moreover AOP is much, much more flexible and powerful. You can ask the AOP implementation: "please start a transaction every time I call a method beginning with "save*" and taking one argument" or "if method returning Customer throws an exception subclassing from IllegalAgumentException, call that method again".
AOP is much more than just grouping common logic.
You have not understood what AOP is all about. The idea of AOP is to be able to write
public void foo() {
// some business code
}
instead of writing
public void foo() {
LogManager.getInstance().log("entering foo...");
SecurityManager.getInstance().checkUserInRole("fooer");
TransactionManager.getInstance().startTransaction();
try {
// some business code
TransactionManager.getInstance().commit();
}
catch(RuntimeException e) {
TransactionManager.getInstance().rollback();
throw e;
}
LogManager.getInstance().log("leaving foo...");
}
All the cross-cutting concerns (logging, security, transaction management) are outside of the business code, instead of being mixed with the business code, and repeated ad nauseam.
imagine a transactional, multithreaded java application using spring, jdbc and aop with n classes in m packages all taking part in database transations. Now let's say there is the need to scope an arbitrary set of classes within one transaction. Furthermore there is always one class T within the scope that commits the transaction when called.
Let me give an example for clarity:
Given the packages A,B,Z and classes A.Foo, B.Bar and Z.T.
The following instances of the respective classes are called (possibly by different callers with other classes in between): A.Foo,B.Bar,A.Foo,Z.T
The transactions will be committed only after Z.T is called. Should the application shut down for whatever reason the transaction will never be committed unless Z.T gets involved.
Instances can call each other and, as already mentioned, there is no common entry point calling all instances from a single point of entry (like a service layer) which would make an easy target for spring's transactional tag.
Now the question: can this problem be solved using aspects ? If so, what could be the basic approach ?
Thanks.
You don't need a single point of entry, but you do need the ability to apply the transactional interceptor to all entry points so that re-entrant calls can participate in the same transaction. Assuming that you can do that, you could accomplish this with a ThreadLocal flag and a custom org.springframework.transaction.support.TransactionSynchronization implementation.
You'd modify Z.T to set the ThreadLocal flag when a commit is safe to proceed. In your TransactionSynchronization.beforeCommit() implementation, which is invoked from the PlatformTransactionManager, you can check the flag and use that to determine whether to allow the commit to proceed. You can force a rollback by throwing a RuntimeException if the flag is not present.
One caveat would be if you have other types of transactions (that don't involve the 3 co-ordinating classes you've described), you'll need to ensure that they don't get rolled back inadvertently. To do this, you could flag this "special transaction" in A.Foo, B.Bar and Z.T via another ThreadLocal flag, then check that flag in a guard clause in the beforeCommit() method mentioned above. Pseudocode:
void beforeCommit() {
if in special transaction
if commit flag not set
throw new RuntimeException("cancel transaction")
end if
end if
end
And, obviously, this is a hack and I wouldn't advocate doing in a greenfield system :).
Spring's idiom would recommend having a service interface that knows about units of work and a persistence interface that deals with relational databases. The methods in the service interface should map closely to your use cases. The service implementation knows about all the model and persistence packages and classes it needs to accomplish the goals of the use case.
"Instances can call each other and, as already mentioned, there is no common entry point calling all instances from a single point of entry (like a service layer) which would make an easy target for spring's transactional tag."
This sentence tells me that you're doing things in a manner that doesn't lend itself so easily to Spring's idiom. It's hard to tell exactly what you want, but it sounds like you're tossing aside two of the most important layers that Spring recommends. If it seems difficult to go against the grain, perhaps it's your design that needs reworking.
"...different callers with other classes in between..." - maybe you need to declare transactions individually on these callers.
You can declare transactions in XML config using aspects, either with Spring AOP or AspectJ. Spring 2.5 and higher now give you the option of using annotations if you prefer them to XML configuration.
Your description is terribly confusing to me. Maybe that's part of the reason you're having difficulty with it as well. I'd rethink or clarify.
With spring transactions and aop you can do it but it'll be a bit of "hack"...
You'll need to put the start of the transaction at all the entry points - you can only commit from when you started the transaction, and you'll need a second aspect inside this one to control whether to commit or not.
Now the only way to tell spring to roll back a transaction is to throw an exception across the transaction boundary. Thus what you'll need to do if you enter that area Z which will cause the commit you'll then need to put something in the thread local (also possibly via an aspect) which that "inner" aspect will find and thus not throw the exception to roll back the transaction. If you do not enter Z then the thread local will not get the flag and when you go back across the inner aspect an exception will get thrown to roll back the transaction. You'll probably have to swallow that exception.
I have used AOP within spring with no real problems, mainly for transaction management, for which it works a charm.
My question is this... the only examples I've seen for AOP so far is to pointcut a class that you have created yourself. Is it possible to pointcut a class within a third party library, for example a database connection class. The context is that I wish to create some logs and gather information when an oracle data source executes a call to the database, which is unfortunately contained within a stack of oracle class files. How would you pointcut this class/method when the SQL is executed?
I think this will work:
Let Spring be responsible for initializing your DataSource
Apply an aspect against the getConnection() method on your DataSource
In your advice, wrap the returned Connection in a new class ("LoggingConnection") which implements Connection and delegates all methods to the "real" wrapped Connection (I believe this is the Decorator pattern)
Add whatever logging code you need to the "LoggingConnection" class
Bear in mind that this approach creates a proxy of the original DataSource and delegates to it for each method call. In the context of a database operation this shouldn't create a lot of additional overhead. You will want to be extremely careful what your code is doing, lest it throw exceptions and prevent Connections from behaving appropriately. Perhaps use try/catch/finally and put the call that delegates to the "real" Connection in your finally block.
Another totally different approach would be to use AspectJ and do load-time weaving. That way you can decorate the class with new functionality as soon as the ClassLoader loads it.