How to override all setters of the fields with custom annotation? - java

Some fields of some classes in my Spring Boot project are annotated with my custom annotation.
How can I tell Spring to override all setter methods of those annotated fields, so that, when setter of those fields are called, it will set that field to "" or null?
I dont want to go around and change my classes, because there is a lot of them.
I just want to code all needed logic on one place.
Consider that I have, for example, 100 classes and that I dont know their names, I just know that they have some fields with custom annotation, meaning I need some generic solution.

Related

Spring constructor injection with lots of fields

I have a Spring component that has 8 members.
I am currently autowiring these 8 members with field injection.
I now want make these members private final, and do constructor injection to set them.
This is easy enough to do, but now I have a component constructor with 8 parameters.
I know I can use setter injection and set these values in an XML file, but this I don't want to do.
Are there any other alternatives?
EDIT:
This component just does a single thing. But that involves calling several other services. Hence the 8 injections
Firstly, there is no alternative.
Secondly, if a contructor has 8 parameters, it is not designed properly. I think you should rethink about the class structure and responsibility. Consider splitting the class into two or three separate beans and inject those.
If a constructor has 8 arguments, in most cases it will be vioalating SRP(Single Responsibility principle)
First of all you can set the initial values of these parameters in an .properties file and then read this property file as a pojo configuration class and it is very easy in spring to convert .properties file into pojo.
so the constructor will be something like this
#Autowired
public Temp(ConfigPojoClass config) {
.....
}

How to Inject a Function inside a set of classes

I have a usecase where i want a particular class or a spring bean to be injected in a set of classes that have a particular annotation. Basically i want a few set of methods to be added to the annotated classes.
Suppose i have a class annotated with annotation #Finders. Then i want the class to be able to use some predefined methods like
findById(), findByName() etc to be available to the class and we should be able to call these functions in a static context like
User.findById() and so on.
Is there a way to inject these methods to the class using Java or Spring. Can i use reflection to do this.
Is there any other way i can get this done in java.

Spring getter and setter dependent?

I would like to make sure if I understand this correctly. Spring needs a setter to inject a field reference? Couldn't it do it by just detecting it as a public field?
Is there an alternative to this. From what I understand Java EE's #Inject annotation can do this without any problem. But I have always been inclined more to Spring.
This depends on how you're creating your bean. Spring does not require setters. There are a number of other ways:
Autowiring (with or without Qualifiers) via annotation at the field level
Constructor injection (either by xml or annotations in the code)
Public fields (as you suggested) might work, though i have never tried it, and would advise against it even if it does.
Unfortunately, the XML approach does not look into private fields (that i know of). You either need to add a setter, use the constructor, or set up some sort of autowiring.
Keep in mind, autowiring can be combined with XML. Spring will pay attention to your wiring annotations even if you create your bean via xml (as opposed to something like #Component and component scanning).
It is not necessary to have Setter to inject a reference, you can use Autowire on a public variable of a class or on the setter method, u can also inject beans using constructor-arg which is a good way of injecting dependencies and autowiring can be done on Constructors also. #inject also does the same functionality as #autowired, however #Autowired has an additional behaviour where it internally also uses #required attribute, to see if the bean has a references and injected properly.
Spring provides several alternatives for DI besides setter injection. For example, you can use constructor injection. Alternatively, you can use Spring's #Autowired annotation for constructor, field or setter injection. Since you mentioned it, I guess that you would also be interested in knowing that Spring supports the #Inject annotation.

Programmatically instanciating objects thats classes have Spring life-cycle annotations

I am testing a set of classes that will, ultimately, be used to create beans within Spring contexts. I am using JUnit for testing. I want to ensure that when instances of these classes are instantiated programmatically within a test that the life-cycle methods and the #Required setters are correctly called. I know I can do this via a plain-old-java-proxy but am wondering if there exists specific tools within Spring (or elsewhere) that will help me.
I am looking to write something like
X x = ???.newBeanInstance(X.class);
x.setFoo(foo);
x.setBar(bar);
x.$postConstruct();
...
x.$preDestroy();
x = null;
The other, less desirable, option is to just create the context's XML and use it to initialize the instances.
If you bring-up the whole context, you can use the spring-test package and its #ContextConfiguration.
If you want to handle things manually, you are on your own (almost). If you have field injection, you can use ReflectionTestUtils to set dependencies. But apart from that you:
instantiate the object with new X()
call setters
call the initializer method (you should know which one it is)
call the destruction method in the end

Best way to add annotations to inherited methods

I have a number of abstract superclasses from which my concrete class inherit various methods. Some of these methods need to have JPA or JAXB annotations placed on them in the concrete class. Currently I do this via the following:
#MyLocalAnnotations
#Override
public method inheritedMethodHere (yadda yadda)
{
super.inheritedMethodHere(yadda yadda);
}
Is there a way to do this without overriding the method? It seems like such a waste to override a method only to supply local annotations.
Unfortunately, there isn't a better way than what you are doing now. To do what you are describing you will have to override the method, considering that your JPA annotation will need information specific to the concrete class.
With JPA annotations, you actually have two options -- you can annotate the methods, or you can annotate the properties. On our project we've standardized on annotating properties rather than methods, but this won't help you either, as the properties are presumably part of the concrete class. (If they are somehow shared in the super-class, then you REALLY will need to annotate the methods, and override them).
Its hard to make a recommendation without seeing your schema, but if your entity classes have so much in common that they share many properties in the super-class -- might they simply be stored in the same table, perhaps with a differentiating type column?
Or alternatively if they are not nearly identical, might you just reproduce the common properties in each concrete class? You might be causing yourself more work rather than saving yourself by trying to capture the common properties in the super class. Since you will have to annotate them individually in the concrete classes, just declare them in the concrete classes. If you need common methods that interact with these properties, a separate Utility class to capture those functions could be the answer.
On our project we DO sometimes use a common super class for entities, but it captures some meta-data about the entity -- nothing that would impact persistence logic. Therefore, no JPA annotations are needed (nor would they make sense) in the abstract class.

Categories