Spring equivalent of Guice's requireBinding - java

What is the equivalent of Guice's requireBinding in Spring?
For those familiar with Spring, but not Guice, here's what requireBinding is useful for:
Suppose you have 4 modules:
security
contains a SignatureHelper interface
web-api
depends on security
contains REST API resources that make use of the SignatureHelper
web-ui
depends on security as well
contains HTML resources that also make use of the SignatureHelper
webapp
depends on both web-api and web-ui (and transitively security)
exists mostly to package both these modules into a single .war file
it also contains an implementation of the SignatureHelper interface
Both web-api and web-ui won't be able to declare their own bindings of the SignatureHelper, as they don't even have a concrete implementation available. And even if they did, together they wouldn't be allowed to both declare the same binding twice.
This is why with Guice, both web-api and web-ui can simply specify a required dependency on the SignatureHelper class, and demand that the application in which their Guice modules are being loaded has previously bound one.
How can I accomplish the same thing in Spring?

Related

Spring: Dynamic registrations of beans, rest-controllers, and more

I am new to Spring and would like to convert my existing applications to Spring Boot.
However, I am using a self-written module framework that allows me to add or remove components or additional functions of the application dynamically at runtime. The whole thing can be compared to plugin frameworks like PF4J or the plugin mechanism in Minecraft servers.
The advantage of this is obvious. The application is much more dynamic and certain parts of the program can be updated at runtime without having to restart the whole application.
Under the hood, a new ClassLoader is created for each module when it is loaded. The ClassPath of this ClassLoader contains the JAR file of the module. Afterwards, I load the respective classes with this ClassLoader and execute there an init method, which contains each module.
Now, I would like of course in connection with Spring that both the dependency injection in the modules functions, and that beans or, for example, rest controllers, which are in the modules, register with the module loading and unregister with the module unloading.
Example: I have a staff module. When I register it, the employee endpoint is registered and is functional. When I unload the module, the employee endpoint is removed again.
Now to my problem:
Unfortunately, I don't know how to implement this with Spring, or if something like this is even possible in Spring. Or are there even already other solutions for this?
I also read something about application contexts. Do I have to create a new application context for each module, which I then somehow "closed" when unloading the module?
I hope you can help me, also with code examples.
This post helped me a bit: https://hdpe.me/post/modular-architecture-with-spring-boot/
In short for each module a new ApplicationContext (e.g. AnnotationConfigApplicationContext) is created. If you want to share beans between the modules, you have to publish them to the main application context.
Beans can be registered at runtime by ((GenericApplicationContext) applicationContext).registerBeanDefinition(name, beanDefinition); at the main Application Context.
Another problem is that additional configurations are required, for example for #RestController or similar, in order for them to work. See other questions on StackOverFlow from me.

Spring - dependency injection - testing with different implementation

One of the main advantage of using spring dependency injection is for testing the functionality using same interface with different implementation without making any changes in the code, that is through injecting these different implementations(dependencies) in configuration file.
Lets take an example where we have developed our application with java configuration/annotation based (No .xml files at all).
We have done a code freeze and have deployed the code in server.
Now for a QA team to perform testing they need to inject different implementations for the interface by making changes in configuration file without touching code.
If its a .xml file, devOps team can inject the different implementation by injecting that bean name and can restart the server.
But since we have used the annotations based/java based configuration, How can we achieve this ?
Thanks in advance.
One of the main advantage of using spring dependency injection is for
testing the functionality using same interface with different
implementation
One of main advantages of Spring is indeed the dependency injection facility.
But you will also find very often cases where you have beans with a single implementation :
beans that rely on an interface but there is only one implementation for it.
bean that don't rely on any interface but are straight classes that you want to turn into injectable beans.
We have done a code freeze and have deployed the code in server. Now
for a QA team to perform testing they need to inject different
implementations for the interface by making changes in configuration
file without touching code.
Spring and more generally dependency injection pattern/frameworks are not designed to perform hot swapping or implementation modification of a deployed component without repackaging the component.
At startup, Spring creates its context and loads all required beans for the application in its container.
If you want to change configurations of some beans, the most clean and side effect less way is destroying the spring context/container, repackage the application with the needed changes and restart it.
If its a .xml file, QA team can inject the different implementation by
injecting that bean name and can restart the server.
Ideally, the QA team should test the implementation that you deploy in QA env and that will be used by final users to stay the closest of the real functioning of the application.
Now, if because of some specific constraints, some components to test by the QA should be mocked/stubbed in a some way, just create a different build for that.
Spring Boot Profile and Maven Profile features can help for.

Factory which is not dependant on implementation

I have an api which has some base implementations. I have a factory which gives the instances of that api to the clients.
I want to change my factory to make it more generic so, if a new implementation of the api will be generated and its jar file will be put in classpath, the factory will understand it and any changes wouldn't be needed.
Use the java SPI, Service Provider Interface.
API jar - Provide one single interface.
Provider jar - Provide implementations in jars. You can even put several implementations in a jar. In a text file META-INF/services/my.package.MyInterface one lists implementing class(es).
Application - In the application the implementing jar should not be needed for compilation:
in maven scope runtime.
The service discovery happens with a ServiceLoader<T>:
public static void main(String[] args) {
ServiceLoader<MyInterface> loader = ServiceLoader.load(MyInterface.class);
for (MyInterface api : loader) {
api. ...
}
// Or take the first implementation:
MyInterface api = loader.iterator().next();
}
You could provide a class in the API jar with a static function for that discovery mechanism.
Advantages:
Separation
Several implementations possible
Selection of implementation can be done dynamically
Example of jars
xxx-api.jar
my/package/MyInterface.class
xxx-first-impl.jar
META-INF/services/my.package.MyInterface
my.package.impl.MyImpl1
my/package/impl/MyImpl1.class
public class MyImpl1 implements MyInterface { ... }
myapp1.jar
If you'd like to start with theory. Please read about Dependency inversion principle.
In object-oriented programming, the dependency inversion principle refers to a specific form of decoupling software modules. When following this principle, the conventional dependency relationships established from high-level, policy-setting modules to low-level, dependency modules are inverted (i.e. reversed), thus rendering high-level modules independent of the low-level module implementation details.
A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
B. Abstractions should not depend on details. Details should depend on abstractions.
The principle inverts the way some people may think about object-oriented design, dictating that both high- and low-level objects must depend on the same abstraction.
Dependency Injection Library
As for specific implementations, you have many in Java. Specifically for the Dependency Injection approach. Spring Framework obviously comes to mind. But you can also look at Java EE Context and Dependency Injection.
Interface Injection
You can also...
Load the Jars manually : How should I load Jars dynamically at runtime?
Use Interface Injection : Spring interface injection example ( This title says Spring, but the answers show no Spring is needed for Interface Injection )

How to use spring service interfaces and implementations in gwt by coding less?

i have a maven project having two modules; one spring module and one for gwt module. gwt module depends to spring module. And i have XService interfaces and XServiceImpl implementations as Spring beans annotated as #Service("myXServiceImpl").
I want to call myXServiceImpl bean's method from gwt client-side. For this purpose i write proper gwt classes; XGWTService, XGWTServiceAsync, XGWTServiceImpl and XGWTServiceImpl uses XService by #Autowired (I use spring4gwt and XGWTServiceImpl is a spring bean annotated as #Service("myXGWTServiceImpl"))
Actually, i want a practical solution as simple as defining only XGWTServiceAsync which is annotated with #RemoteServiceRelativePath("spring4gwt/myXServiceImpl")
I wonder if there is an easy way to call my spring beans without coding extra 3 classes(XGWTService, XGWTServiceAsync, XGWTServiceImpl)?
Thanks in advance
Put the XService interface and all the classes used by it in a separate package. Make the XService extend RemoteService. You can then define a GWT module that includes those classes. Package the source along with the jar file. Inherit the GWT module in your main GWT module and implement only the XServiceAsync interface.
You can also do away with manually implementing the XServiceAsync - the maven GWT plugin has an option to generate the Async version from the interface.
The only awkward thing in this is making the XService implement the RemoteService interface of GWT and thus having to make your service implementation depend on the GWT jar. But since it doesn't come in the way of implementation that is something that we can live with.
The other option is to just create a XGwtService interface that extends XService & RemoteService - not add any additional methods into this. On the server just the XServiceImpl should be sufficient.

How to choose between methods of acquiring dependencies?

I've seen at least three ways of acquiring dependencies in a Java object without coupling the object to the creation of the dependency;
Dependency Injection
- some framework injects a required object into another object based on an external configuration, example: Spring managed beans
Dependency Lookup
- a class looks up a required dependency in some kind of directory service, example: JNDI lookups in a Java EE container
Static Factories
- an object in a global scope provides instances on demand - the standard Java SE APIs seem to be littered with these, example: java.util.Logger.getLogger(name), java.util.Calendar.getInstance()
What guidance can you provide as to which is most appropriate for a situation?
I prefer dependency injection, because the object need not know how it acquires the references it needs.
Dependency lookup still requires the object to know about the lookup service and its URL.
Static factories are similar to lookup services.
I prefer dependency injection.
When I talk about DI with Spring Framework I see following
It's supported by IDEs (error check, visualization).
You can setup other needed stuff like AOP, properties loading, ...
You have big config possibilities - XML, annotation, JavaConfig
Can be use also in desktop application.
These outbalance every negatives like dependency on another library. Why should I use another approach?
This really depends on the context. If you are writing a self-contained Maths API you might want to use static factories because the code will be less verbose, setup-free and maybe more efficient. If you need to access/provide a remote dependency, a JNDI/LDAP lookup, or ESB messaging would work well. For injecting your services/DAO's/datasources into your typical enterprise server code you'd be better off using one of the common D.I. frameworks like Google Guice or Spring.
There is no single 'best' solution in software design; it's always a tradeoff.

Categories

Resources