how to build Generic CRUD Controller using Spring Proxy & BeanPostProcessor - java

I'm planning to build a generic infrastructure for MVC CrudController and Generic CrudService using interface Proxies and custom annotation processing, because i have multiple endpoints in my project with the same CRUD pattern.
the bottom line is - defining interfaces of CrudController and CrudServices and create a ProxyBean for my interfaces and process cutsom annotation, i want to achieve the same pattern as spring data repositires where you need to define you repository interface only,
for example:
interface CrudController<T>{
//crud method...
}
interface CrudService<T>{
//crud method...
}
class GenericCrudControllerImpl<T>{
private CrudService<T> service;
//crud methods implementation and call service crud methods
}
the usage of this pattern would be like the following:
#CrudRestController(service=PersonCrudService.class) //PersonCrudService implements CrudService
class CrudPersonController implements CrudController<Person>{}
i know i should use Spring's FactoryBean<T> interfaces along with BeanPostProcessor, but the problem i don't know how to read the generic parameter of my CrudController, e.g. Person to be able to instansiate my generic implementations with the generic paramters, e.g. Person.
i need assistance how to use the ProxyBean pattern and BeanPostProcessor the right way to acheive the implementation above, i couldn't find any useful examples on the web.

Related

Spring functional bean registration of #Repository interface

I migrated a Spring-Cloud-Function to use Functional Bean Registration.
I can register the Function that contains my application logic.
However my logic should be able to autowire a dynamodbRepository which I currently defined like this:
#EnableScan
public interface BookRepository extends CrudRepository<CodingTip, String> {
List<Book> findAllByAuthor(String author);
}
Since I am not scanning for beans anymore no bean is created of type BookRepository. This means that I have to register it myself. But I do not want to define the implementations of all the CRUD methods.
Currently I could write:
context.registerBean("repository", BookRepository.class, () -> new BookRepository(){ ... });
How would I register the BookRepository bean while still maintaining the advantages of all the CRUD methods being implemented for me?
Check out this incubator project called Spring Fu. Although it is written in Kotlin, it might help you find a way to do this.
Take a look here to see how Sébastien did it with a MongoDB database.
Creating a DynamoDB client and an implementation instead of using an annotated interface would be the way forward I guess.
Hope that helps! :)

Wiring beans that do not implement an tag interface in list using Spring

I have a set of classes that extends an abstract class Executor. Let's say that these classes are ExecutorOne, ExecutorTwo and ExecutorThree. Then, I have a fourth class extending the Executor type, ExecutorFour, but also implementing the interface NotUsable.
I am using Spring 4.x to inject an instance of all the above beans into a list.
#Autowired
private final List<Executor> executors;
Is there any mechanism that allows me to not inject a bean of type ExecutorFour inside the list executors? I want the list executors to contain only three beans, respectively of type ExecutorOne, ExecutorTwo and ExecutorThree.
I tried to have a look at the #Conditional annotation, but it seems it is no use in this situation.
Thanks in advance.
There is another option, it helps to achieve what you try, but doesn't answer the question directly.
Spring doesn't have an exclusion mechanism like this, after all, all 4 beans are valid spring beans and are created.
However, you can work with Usable interface, instead of NotUsable marker interface. Here is a (pretty much self-explanatory) example:
interface Executor {}
interface UsableExecutor extends Executor {}
class Executor1 implements UsableExecutor{...}
class Executor2 implements UsableExecutor{...}
class Executor3 implements UsableExecutor{...}
class Executor4 implements Executor {} // note, doesn't implement UsableExecutor
#Component
class SomeClassWithUsableExecutors {
private final List<UsableExecutor> usableExecutors;
// an autowired constructor - only 3 elements will be in the list
public SomeClassWithUsableExecutors(List<UsableExecutor> usableExecutors) {
this.usableExecutors = usableExecutors;
}
}
While Spring doesn't provide a "exclude these classes" grammar for #Autowired, it provides a "include these classes" support instead, in the form of
#Qualifier.
The way this works is to create a custom qualifier that you'll apply at the class level to the Executor classes that you would want to be #Autowired at runtime. Spring does the rest to make sure that the undesired classes don't get into the list:
Create your custom qualifier, to be applied to the desired classes:
#Target({ElementType.FIELD})
#Retention(RetentionPolicy.RUNTIME)
#Qualifier
public #interface Usable {
String value();
}
Apply your qualifier at the injection point:
#Autowired
#Usable
private final List<Executor> executors;
What the above now does is that only Executor classes with the custom #Usable qualifier will be injected into executors

Create proxy for a interface, which could inject by #Autowired, proxy invokes different implement by key parameter

I want to define a annotation like #PlatformRelated, once it is marked in a interface, there will be a proxy bean at spring context, and this proxy bean should be #Priority.I want this proxy could invoke different implement according to key parameter #KeyPrameter.And I still wanna use spring features like #Async,#Trasaction,etc... at my Implement1 and Implement2.
#PlatformRelated
interface MyInterface {
method(#KeyPrameter String parameter);
}
#Component
class Implement1 implements MyInterface {
method(String parameter){
//do something 111
}
}
#Component
class Implement2 implements MyInterface {
method(String parameter){
//do something 222
}
}
#Service
class BusinessService{
#Autowired
private MyInterface myInterface;
public void doSomething() {
myInterface.method("key1");
//Implement1 work
myInterface.method("key2");
//Implement2 work
}
}
Do you guys have some good idea to complete it?
I must admit I haven't totally understood the meaning #Priority, however, I can say that if you want to implement this feature in spring, you should probably take a look at Bean Post Processors.
BeanPostProcessors are essentially a hook to Bean Creation process in spring intended for altering bean behavior.
Among other things, they allow wrapping the underlying bean into the proxy (CGLIB/java.lang.Proxy if you're working with interfaces, or even using programmatically Spring AOP), these proxies can provide a hook to the method execution that can read your annotations (like mentioned #KeyParameter) and execute a code in a way similar to Aspect's code that you already make use of.
Not all bean post processor wrap the bean into the proxy. For example, if you want to implement a BPP that uses "#Autowire", you will return the same bean, just "inject" (read, put by reflection) its dependencies. On the other hand, if you want to implement with BPP #Transactional behavior, then yes, you should wrap the bean into a proxy that would take care of transaction management capabilities before and after the method execution.
It's totally ok to have a spring bean that gets "altered" by many post processors, some of them would wrap it into a proxy other will just modify-and-return the same bean, If there are many BPP-s that wrap the bean into proxy we'll get "proxy inside proxy inside proxy" (you get the idea). Each layer of proxy will handle one specific behavior.
As an example, I suggest you take a look at existing Spring postprocessors, or, for instance, a source code of the following library: Spring Boot metering integration library
This library contains some implementations of post processors that allow metrics infrastructure integration by defining annotations on methods of Spring Beans.

Using repository annotation when implementing JpaRepostiory in Spring

I'm not sure if I understand it correctly so want to clarify.
If I want to create a repository for my entity eg.:
public interface BookRepository extends JpaRepository<Book, Id> {}
Should I annotate it with #Repository? According to this question #Repository annotation translates exceptions from SQL to persistence ones but doesn't JpaRepostiory already do that? What's the best practice - to annotate or not?
While using JpaRepository you don't need to annotate the interface with #Repository
It is just an interface and the concrete implementation is created dynamically as a proxy object by Spring and the JDBC Exceptions are handled there.
You need to use #Repository when you create a Custom DAO, so that spring creates a bean and handles the exception properly.
You need to annotate it with #Repository so spring knows it should instantiate that class as a bean. The #Component, #Service and #Repository annotations all serve the same purpose in that regard. #Repository narrows the scope to a service that specifically deals with obtaining and storing data.

Spring Data Project - Couchbase Integration

I went over the below tutorials for using couchbase db via Spring
http://projects.spring.io/spring-data-couchbase/#quick-start
I see the below auto wiring in service class. UserRepository is an interface. I assume there should be an implementation which implements this interface and is exposed a bean. I don't see any class implementing this interface or being exposed as a bean. Is it possible to help in explaining how this works?
#Autowired
public MyService(UserRepository userRepository) {
this.userRepository = userRepository;
}
The aim of the Spring-Data project is to create such implementations at runtime for you when you only define interfaces.
It will inspect the packages you configured for scan via reflection and discover xxRepository interfaces in them, at which point it will use a base class provided by the store-specific Spring Data subproject you chose (here Couchbase) to weave together a concrete implementation of xxRepository and inject it.

Categories