Spring - Loose coupling between different application modules? - java

My current project has multiple modules (NOT Java 9 modules) and I'm looking for a good way to do loose coupling between Spring-based application modules.
From my understanding, I could #Import configuration classes (from other application modules). But it has some limitations:
Dependency on implementation classes of other modules
No clear API to be exposed for the consumer modules
The disadvantages would limit the ability to replace a module by an equivalent module which implements same API.
I'm thinking about using interfaces for module APIs and the #Configuration classes would implement the API interfaces. And the #Import will be replaced by dependency on exposed API objects. I have prototype code here https://github.com/tha2015/springmodules/blob/master/src/main/java/dsl/Main.java
Is there a better way to do loose coupling between application modules?
Thanks.

Related

Spring equivalent of Guice's requireBinding

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?

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 )

Is this project structure valid?

I have a dilemma: In the university we learn to create modular software (on java), but this modularity is explained using a single project with packages (a package for business, another one for DAOS and another one for the model, oh and a last package for frontend).
But in my work we use the next structure:
I will try to explain:
First we create a java library project where the model (entities classes) are created in a package.
Next we create an EJB named DAOS and using the netbeans wizard we store the DAOS interfaces in the library project in another package , these interfaces are implemented in the DAOS bean.
So the next part is the business logic, we create a business EJB for each group of functions , again using the wizard we store the interface in the java library project in another package then is implemented on the business bean.
The final part (for the backend) is a bean that I have suggested: a Facade bean who will gather every method of the business beans in a single bean and this has an interface too that is created in our library project and implemented in the bean.
So the next part is call the facade module on the web project.
But I don't know how valid or viable is this, maybe I'm doing everything wrong and I don't even know! so I want to ask your opinion about this.
Storing the interfaces of DAOS, BusinessBeans and Facade in the model project is not a good choice.
Arguments against:
Data structure (entities classes), business logic (BusinessRemote, FacadeRemote) and technical logic (DAOSRemote) are mixed in one project. They are in different packages but will be delivered in one jar.
Reusing the data structure in other applications will lead to classes in your project that are not necessary for the new application.
Changes in the one of the interfaces will force a rebuild of your projects. If the facade interface needs to be changed, because of new requirements or features, you must change the interface class in your model project. This will lead to a new jar of your project that needs to be distributed.
Suggestions:
Separating implementation and interfaces is a good approach; but go all the way. Create separate interface projects (Business, Facade, DAOS). If you are using some dependency management tool (Maven, Ivy, ...) you will add only dependencies to this interface projects. For your WAR you will include all jars separately.
Good point:
Adding an additional interface as application facade is good. We use this approach to offer different application facades for different user roles, without mixing this role logic into our business logic.

Generic Spring services from external library?

I'd like to define some commonly used or generic service classes that should be used/shared by different projects. These common services should already make use of #Transactional, #Autowired and other Spring related stuff. So, I somehow have to define a spring context for these services to work.
Is it possible to put these services in a single external jar library that can then be used/imported by other (child)-projects? How could I create such a "personal framework"?
What you could do is create a maven (or gradle) module that contains the code you desire to be reusable and also have a spring configuration (either XML or Java Config) that will be imported by the project that uses the module (either with or having component scanning pick up the #Configuration class of the module).

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.

Categories

Resources