In the context of a recent Spring Boot app (v. 2.7.0), there are a number of options for where the #Transactional annotation is applied
Controller or Service?
Almost universally it seems that service is recommended, but it's not entirely clear why.
Implementation class or interface?
Assuming we choose to apply the annotation to our services and those services implement an interface, should we annotate the service interface or the implementation class?
In older versions of the Spring docs, it was recommended to annotate the class
Spring recommends that you only annotate concrete classes (and methods of concrete classes) with the #Transactional annotation, as opposed to annotating interfaces. You certainly can place the #Transactional annotation on an interface (or an interface method), but this works only as you would expect it to if you are using interface-based proxies. The fact that Java annotations are not inherited from interfaces means that if you are using class-based proxies (proxy-target-class="true") or the weaving-based aspect (mode="aspectj"), then the transaction settings are not recognized by the proxying and weaving infrastructure, and the object will not be wrapped in a transactional proxy, which would be decidedly bad.
But this advice does not appear in the 5.2.X version of the docs, so I'm wondering if it still applies? Based on my testing it seems that applying the #Transactional annotation to interfaces does work in a Spring Boot app with the default proxying behaviour.
#Transactional is most commonly used at service level, though there is nothing stopping you from making your controller methods transactional. It really depends on how you structure your application.
IMHO making your service layer transactional is a better approach. It is typically at this level that you might be calling other persistence methods (DAOs, repositories, etc). There could be reads/writes across multiple tables, so it makes the service layer a good place to define transaction boundaries.
Related
I am trying Google Guice as Dependency Injection framework for my new project and shifting from spring.
I have to write multiple providers using #Provides, where instance created from one provider will be used as an input to other providers in the separate modules (sometimes the same module).
For binding the instance generated from the module, I am using Guice's
#BindingAnnotation
to create a custom annotation.
I just wanted to know how does the precedence works in Google Guice?
Like in spring we had a #Dependson annotation for bean creation, is there an alternative in Guice or Guice smart enough to generate a dependency graph by itself?
Does Binding the instances of providers using annotation created from #BindingAnnotation enough?
[is] Guice smart enough to generate a dependency graph by itself?
I'm not familiar with Spring, but my gut-feeling is Yes.
Does Binding the instances of providers using annotation created from
#BindingAnnotation enough?
As long as the provider has been annotated as providing something (using #Provides), Guice will use that annotation as a default, unless otherwise overridden inside a module.
However, using BindingAnnotations does include some code in a Module to bind it together,
https://github.com/google/guice/wiki/BindingAnnotations
bind(CreditCardProcessor.class)
.annotatedWith(PayPal.class)
.to(PayPalCreditCardProcessor.class);
So I suspect that Binding Annotations based annotations have stronger strength then #Provides and as long as you have the counterpart in the module, is more then enough to bind your providers together.
In the repository layer I define normal data operations such as inserting, finding and so on. I am using Spring and I have the #Repository annotation above the class. Is it bad to use this class directly in the #Controller class for instance? Should all repositories always have a service layer that just delegate to the repository layer?
It totally depends on your choice. In Spring Roo, you don't just skip the Repository or Service layer, but use a Rich Domain Model where you have the data access logic in the domain itself. Frameworks like Groovy on Grails use a single Repository layer. So i think its OK to use it directly in the Controller.
I similarly asked what use are EJBs? An answer said this:
your [service layer] typically orchestrates application of business logic but more often than not does not actually perform it, it is usually a very thin wrapper.
The service-layer methods can define the operations that are transactions, and which therefore have annotations to get AOP transaction support added automatically for you. See also an answer to a related question, which says:
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.
IN spring docs it's written
The most important concepts to grasp with regard to the Spring Framework's declarative transaction
support are that this support is enabled via AOP proxies, and that the transactional advice is driven by
metadata (currently XML- or annotation-based).
So If i use
<tx:annotation-driven proxy-target-class="true" order="100"/>
in config file and not use #Transactional annotation on my beans. Would transaction still be supported, as I am using AOP and transaction Interceptor should be built-in to my AOPs thus no use of explicitly using #Transactional annotation.
Thanks,
No, you'd still have to use the #Transactional annotation. AOP proxy is only used to inject the transaction related code into your code.
< tx:annotation-driven /> is used to auto detect the '#Transactional' annotation .So it's necessary to have one . Reference here.
The proxy-target-class="true" decides whether Spring should use JDK dynamic proxies or CGLIB class based proxies . See the reference for more info . Basically if your class implements atleast one interface, JDK dynamic proxies are used . If you have a class MyDaoImpl extends MyDao and in your service , you inject the dao reference via MyDaoImpl myDaoImpl , JDK dynamic proxies will not work if the annotations are on your interface as class bases proxies are created with proxy-target-class="true" and #Transactional annotation is not inherited .
The reason why your queries seem to work without #Transactional may be because you are using hibernate template which opens and closes the transactions internally . From Spring 3 , it is recommended to inject sessionFactory directly and not to use hibernate template .
Hope this helps.
In my company the usage of the Spring framework is discouraged and instead Java EE 6 is promoted. But recently I read about Springs #Transactional annotation at Using #Transactional and think this could be really useful for our code.
As far as I understand a method annotated with #Transactional will either reuse an already existing transaction or open up a new transaction if no active transaction exists when calling that method. Is there something analogous (e.g. a similar annotation) available in Java EE 6?
EJB components have this transactional control in Java EE. You can set the transaction of a method on the EJB to be Required, RequiresNew, Supports, etc. You would almost always use a Stateless Session Bean (#Stateless) for the requirements you describe:
> #TransactionAttribute(value=[MANDATORY,
> REQUIRED, REQUIRES_NEW, SUPPORTS,
> NOT_SUPPORTED, NEVER]
Required, the default, will re-use an existing txn if there's one running or create a new one if there is not. Java EE 6 ships with EJB 3.1, so you don't even need the Business Interface and you can package the EJBs in the WAR file if you want. Therefore you are using EJBs, but to the developer they are much easier to integrate if all you want is JTA support.
This is a useful cheat sheet for the EJB annotations and there are numerous guides if you Google for them.
Java EE 7 now contains #javax.transactional.Transactional.
It acts quite the same as the spring annotation.
In Java EE 6, one may annotate the EJB bean class itself, or the individual business methods in an EJB (both session EJBs and MDBs) with the TransactionAttribute annotation. This can be applied only if you use container managed transactions.
Valid values for the annotation are defined in the TransactionAttributeType annotation:
NOT_SUPPORTED
SUPPORTS
REQUIRED
REQUIRES_NEW
MANDATORY
NEVER
The semantics of these values haven't changed from the earlier versions of the EJB specification. These annotations are available since Java EE 5, when annotations were introduced in EJB 3.0. Note that, some of the values are not applicable in certain scenarios - MDBs for instance cannot be annotated with anything but REQUIRED and NOT_SUPPORTED; any other values would not make sense for container managed trasactions for a MDB (after all, the container must either create a transaction or musn't, in this case).
If you want a quick overview of how the transaction attributes compare between the EJB 3.0 and Spring models, I would gladly point you in the direction of Java Transaction Design Strategies. Disclaimer: I'm just a satisfied reader of this book.
EJB's (stateless and stateful) are default transactional components, default transactional property is REQUIRED, similar to spring..
I've noticed recently that spring can wire up my ejb's for me if I annotate the ejb with #Interceptors(SpringBeanAutowiringInterceptor.class). I've never actually done this so don't know the details.
I was wondering, is there a way to get this to work with other kinds of beans, for example, #WebService annotated ones as well.
At the moment in my web service classes (because the application server manages them) I have to load the dependencies from the BeanFactory and would thus prefer to have them autowired.
I know I could use the #Configurable annotation but am not particularly keen to have to specify and agent on the VM.
Is this possible?
Once again, spring has thought of this use case and catered for it!
The problem is that #WebService is not a spring annotation, it is a JAX-WS annotation and thus classes that are annotated with #WebService to be exposed as web services are not managed by spring, but their life cycle is managed by JAX-WS.
The way to handle this case is to have the JAX-WS managed bean extend org.springframework.web.context.support.SpringBeanAutowiringSupport - this will enable the #Autowire annotation, for example, to work in this bean. see here for more information
Yes, of course. There's #WebService, #Repository, #Controller, #Service, #Endpoint, and other annotations in Spring. Here's an example.