From spring reference doc
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.
Though it only talks about interfaces, abstract classes are considered as non-concrete as well.
So if i have an abstract class
public abstract class BaseService{
//here is a concrete method
#Transactional
public void updateData{
//do stuff using dao layer
}
and a concrete class which extends the class
public class SpecialService extends BaseService{
//body of class
}
Now if i call specialService.updateData() from my controller class will it be transactional?
Granting that you have actually configured Spring transaction management correctly, using #Transactional on an abstract superclass will work, since #Transactional is itself annotated with #Inherited and from it's Javadoc we have:
Indicates that an annotation type is automatically inherited. If an
Inherited meta-annotation is present on an annotation type
declaration, and the user queries the annotation type on a class
declaration, and the class declaration has no annotation for this
type, then the class's superclass will automatically be queried for
the annotation type. This process will be repeated until an annotation
for this type is found, or the top of the class hierarchy (Object) is
reached. If no superclass has an annotation for this type, then the
query will indicate that the class in question has no such annotation.
Note that this meta-annotation type has no effect if the annotated
type is used to annotate anything other than a class. Note also that
this meta-annotation only causes annotations to be inherited from
superclasses; annotations on implemented interfaces have no effect.
To actually see that #Transactional is annotated with #Inherited check out it's Javadoc
Related
I am working with Spring Restful and Hibernate. To remove the redundancy in code I want to avoid the object creation of DTO in each and every methods and want to declare it with #Component annotation, I want to know is there any specific rules for DTOs as we have some guidelines for POJO and JavaBeans.
Check Spring Doc
https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-stereotype-annotations
7.10.1 #Component and further stereotype annotations
Spring provides further stereotype annotations: #Component, #Service, and #Controller. #Component is a generic stereotype for any Spring-managed component. #Repository, #Service, and #Controller are specializations of #Component for more specific use cases, for example, in the persistence, service, and presentation layers, respectively. Therefore, you can annotate your component classes with #Component, but by annotating them with #Repository, #Service, or #Controller instead, your classes are more properly suited for processing by tools or associating with aspects. For example, these stereotype annotations make ideal targets for pointcuts. It is also possible that #Repository, #Service, and #Controller may carry additional semantics in future releases of the Spring Framework. Thus, if you are choosing between using #Component or #Service for your service layer, #Service is clearly the better choice. Similarly, as stated above, #Repository is already supported as a marker for automatic exception translation in your persistence layer.
You can create a static method which returns the Object of your DTO class and you can call this method from anywhere to get the instance of that class like this..
private DTOObject dtoObject;
public static DTOObject getInstance() {
if(dtoObject == null) {
dtoObject = new DTOObject();
}
return dtoOject;
}
Hy,
How #Autowired works in an attribute declared in an abstract class if its not inherited in the subclasses. What spring does under the hood in order the subclasses have the dependency injected in them if #Autowired annotation is not inherited in the subclasses?
Thanks
There's no such thing as a not inherited field in subclasses in Java. The private fields get inherited just as any other non-static field, they're just not visible in the subclass code. They can still be accessed with reflection though. Spring will have no problem autowiring such fields.
I have seen a lot of #Validated annotations in the DAOs interface that I didn't write. For example:
#Validated
public interface CompanyDAO extends BaseDAO<Company> {
public List<Company> list();
What behaviour should I expect from this:
Validating all the objects passed to the DAO before saving them into the database?
Validating all the objects that the DAO retrieves from the database?
Both of them?
Nothing at all. This annotation should not be placed in DAO interfaces.
Just a few pointers which you might not be aware of:
8.8 Spring Validation of 8. Validation, Data Binding, and Type Conversion in the manual specifies that
In order to be eligible for Spring-driven method validation, all target classes need to be annotated with Spring’s #Validated annotation, optionally declaring the validation groups to use. Check out the MethodValidationPostProcessor javadocs for setup details with Hibernate Validator and Bean Validation 1.1 providers.
MethodValidationPostProcessor says
Applicable methods have JSR-303 constraint annotations on their parameters and/or on their return value (in the latter case specified at the method level, typically as inline annotation), e.g.:
public #NotNull Object myValidMethod(#NotNull String arg1, #Max(10) int arg2)
Target classes with such annotated methods need to be annotated with Spring's Validated annotation at the type level, for their methods to be searched for inline constraint annotations. Validation groups can be specified through #Validated as well. By default, JSR-303 will validate against its default group only.
So, maybe the answer to your question
What behaviour should I expect
is: Whatever constraints are given in the code.
In my project I have an interface annotated with org.springframework.stereotype.Service tag.
I have two different implementation for this interface.
In my manage bean, I am injecting interface Service class and using its methods.
Now my requirement is, in run time I have to pick particular implementation (lets say based on login user group) so that respective logic can be invoked.
As per my understanding, we can achieve this using Factory pattern in java and achieve the same.
How can we implement this in SPRIng???
Besides suggested related topic above, there is a good thread on JavaRanch.
You can use
#Qualifier("myServiceImpl1") annotation together with #Autowired. In
that case this particular implementation of the interface will be
injected. You should also use the same name with your #Component,
#Service or #Repository annotations e.g.
#Service("myServiceImpl1")
public class MyServiceImpl1 implements MyService{}
public class Consumer{
#Autowired
#Qualifier("myServiceImpl1")
public MyService myServiceImpl1;
}
#Primary together with #Component, #Service or #Repository
annotations in your implementation class, in that case this
implementation will be injected by default.
If you mark a list of some interface type with #Autowired, all
available implementations of this interface will be injected.
#Autowired
public List<MyService> allAvailableImplementations;
i'm wondering if spring loads an interface when declared as an #autowired attribute of an implementation class without having annotated the interface as a #component .
let me describe my problem a bit more :
i have both an interface and its implementation class have the same name but they reside in different packages . i annotated the implementation as #Component("myImplementation") .
but i end up having an exception that says :
conflicts with existing, non-compatible bean definition of same name and class
i'm thinking of excluding interfaces from <context:component-scan , what do you think ?
PS : my interface isn't #Component annotated , the application runs just fine on developpement environement , i only get the error after Proguard obfuscation
Your proguard.conf should be contain:
## ... preserve class annontation (Java EE 1.6 DI)
# Spring3
#-keep #org.springframework.stereotype.Service class *
-keep #org.springframework.stereotype.Controller class *
#-keep #org.springframework.stereotype.Component class *
#-keep #org.springframework.stereotype.Repository class *
proguard forums has more detailed answers.
Annotating your implementation with #Component and not annotating your interface is usually the right way to set things up. Spring's auto-wiring will look for a managed bean of a matching type, and your implementation will match for a field typed to the interface. If your interface is not annotated with #Component, or any Spring stereotype annotation, it should not be loaded into the context during a component scan. So, you should not have a problem if the interface and implementation have the same class name.
Are you sure you've tried not annotating the interface? Are you sure you don't have some other class somewhere else in your project that also has the same name as the interface and its implementation?
Well I think moving interfaces in different package would work because you would create object reference of interface and respective implementation beans would be auto wired to those object references. But you should follow naming conventions. There would be problem when differentiating interfaces and implementation classes as names are same. Follow standards like
interface SomeInterface {
//....
}
for implementation class of SomeInterface
class SomeInterfaceImpl implements SomeInterface {
// implementation....
}