I am developing Spring mvc application.
I have a controller in which I am injecting more than 10 Services.
I am exposing 10+ url from this controller and at a time I am using one or two service objects in each method.
I was thinking of 2 approaches.
Directly inject all services using #Autowired.
Fetch Service from ApplicationContext at runtime whenever required.
Please suggest me which approach is better or both approach are equal in terms of memory usage and time
Thanks
The best approach in most cases is to break up the controller into multiple controllers.
Having too many dependencies is a Code Smell since your controller most likely violates the Single Responsibility Principle.
Both using #Autowired for many dependencies and using the ApplicationContext to dynamically retrieve the dependency are mediocre solutions in most cases and should be avoided whenever possible. What you should do is break up the controller and then use #Autowired (preferably constructor rather than field injection - check out this for more details) to make Spring inject the dependencies.
In the case you describe you should not be worried about the performance or the memory consumption of your proposed solutions, but the maintanability of the code.
Although dynamic lookup of a dependency from the ApplicationContext will be a little slower that accesing the injected by the container dependency, in almost all cases you we never be able to tell the difference. As I mentioned above, the first concern you must be looking at is code maintanability, not micro-performance/memory issues.
Related
I’m taking this udemy course all about Spring Hibernate etc. The course started with explaining how Injection of Control and dependency injection works not in a web perspective just like having simple classes or beans, defining beans and their dependencies inside a config xml file or inside the actual class Using java annotation and then a main class where the beans are created. I understood that despite not really seeing the big benefit of using IoC and DI other than separating roles like creating and maintaining objects and adding dependencies the object needs and I guess when the project is bigger this makes it cleaner and easier to follow right?
However what I don’t understand is how IOC and DI ties in a full spring MVC project. Like I understand using the #Controller annotation means it’s like an #Component and you could make it scan the components automatically when it creates beans but like unlike before there isn’t a main class where beans are created and configured rather I have a controller class where I manually create objects and models and pass that back to the views where I can use the values in the model. I don’t see how I use IoC or DI here? Or is it because it’s a simple project and perhaps the objects we created didn’t have many dependencies?Or are a lot of the uses and implementation done internally or automatically?
I am just struggling to a) see why IoC and DI are that important and b) how are they actually used in a Spring MVC project where you don’t have a main class where you do create beans.
A) Create a project, but don't add any dependency (or web-mvc). Then do it yourself then see how much need time to create configure manually. If it is just a simple mvc project, you can do it manually, but if your project increase day by day then a huge configuration file to maintain your project properly. But when you are professional developer, you don't have so much time to configure all those manually. So here is come the solution IoC and DI. Controller or other anotation are configured in build-in jars. You don't have to worried about to create controller or to create bean, just use them when you neer them. It's save your time as well as headache about is it working or not. It's increase your productivity while your are working on a big project.
B) Yes, there is no main class in web project. To run a web project, you need a server. The server first looking for a configuration (In spring, it's web.xml, dispatcher-servlet). If it available then expand the configuration file, if not then throw an error. In that configuration file, explain everything about the web project. What should do, what is not mandatory, what is entry point etc.
So, IoC and DI are very important because to understand how a web project work behind the scene or how all component work together.
IoC is a process whereby objects define their dependencies, that is, the other objects they work with, only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse, hence the name Inversion of Control (IoC), of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes, or a mechanism such as the Service Locator pattern.
In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application.
The advantages of this architecture are:
decoupling the execution of a task from its implementation
making it easier to switch between different implementations
greater modularity of a program
greater ease in testing a program by isolating a component or mocking its dependencies and allowing components to communicate through contracts
Inversion of Control can be achieved through various mechanisms such as: Strategy design pattern, Service Locator pattern, Factory pattern, and Dependency Injection (DI).
You can go with Annotation based configuration, where you can define #Configuration class and return the required beans using #Bean annotation.
Also you can use #Component to your POJO class to treat it as Spring bean.
Front-End dev here working on my first Java Spring Boot API. I've been reading many articles on the "best practices" in Spring/Spring Boot and have been attempting to refactor my code to follow those practices.
Below I have an example of a generic class I use to handle all HTTP requests for my various services. Originally I had this class annotated with the #Component annontation, but as I mentioned I am trying to learn and follow Spring "best practices." In particular I am interested in implementing what this article on best practices describes (Number 3 & 4 in the article). That says one should avoid using #component, because we don't want to be tightly coupled to the Spring framework and we want to avoid "entire class path scanning."
#Slf4j
public class HttpService {
private HttpServletRequest request;
private RestTemplate restTemplate;
public HttpService(HttpServletRequest request, RestTemplateBuilder restTemplateBuilder) { ... }
public String get(String url, String id) { ... }
}
With the #component annotation my service works as expected, but when I remove it I get the exception:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
This seems to be a pretty common exception in Java as there is a LOT of questions about it, but those solutions have not worked for me.
My question I'm hoping the community can help me answer is two part:
How do I correctly make this a useable generic class that is not tightly coupled to Spring?
Is this actually a correct approach for Spring development or am I reading too deeply into this article?
That says one should avoid using #Component because we don't want to be tightly coupled to the Spring framework ...
It says we don't want our domain classes to be tightly coupled to Spring. There is a difference between HttpService (which is bound to the web context and depends on Spring's RestTemplateBuilder) and MySuperSpecificDomainCalculator (which should keep working regardless of the context it is put in).
... and we want to avoid "entire classpath scanning."
I see nothing extremely evil in using classpath scanning. You may let Spring scan a small set of packages. You may point exactly to where your Spring-dependent classes reside. A #Configuration with #Bean methods is an alternative, and sometimes the only one.
How do I correctly make this a useable generic class that is not tightly coupled to Spring?
You are designing a web layer. You are choosing a technology to use. You decided to go with Spring Web. At some point, you will have to bind Spring's classes to yours. As you already did. HttpService is dependent on Spring regardless of the annotation. It takes RestTemplateBuilder which is a Spring class.
And there is nothing wrong. You need to write such classes to integrate the framework into your application and to make it work for you. Just make sure the line between the Spring world and your domain world is well-defined.
Is this actually a correct approach for Spring development or am I reading too deeply into this article?
The article is reasonable. Your HttpService looks a valid #Component to me. Don't overthink it.
Looking at the article you have linked, I think there is a misunderstanding on the term "domain". The "domain" is where the application generates its value. Taking Steam as an example, the capability to search and buy games generates (business) value. A HTTP service, on the other hand, is a technical detail. It is necessary, yes, but generates no value on its own. So point 3 and 4 of the article do not apply to the HttpService.
In a typical web application, you have at least three layer:
One layer providing the the API: those are your endpoints and all objects that are used by the API. This includes, for example, entities representing the requests and responses passed through/returned by the endpoints.
One layer providing Persistence: Typically, these are repositories, DAOs, or whatever persistence model you want to use. Again, everything needed by the persistence unit should be included in this layer.
One layer holding the actual domain: this is what we talk about when we talk about the "domain". Here we see what the application actually does.
Now comes the tricky part: The web and the database are nothing else than I/O channels. they could be a CLI and some files, HTTP requests/responses and a database or whatever will be developed in the future. A good software design allows for easy swapping of the I/O channel, while preserving the domain-specific code. You see this in many applications:
OpenShift has a REST API and a CLI
AWS has a REST API and several CLIs, many are 3rd party
Steam has a web storefront, a desktop app and a mobile client
Keycloak allows pulling authentication information from different sources (LDAP, OAuth2/OIDC, database,...)
But to get this flexibility, we have to segregate somewhere. What is a technicality? What is domain? How clean do I want/have to decouple? In your concrete case: Does it matter whether you bind yourself to spring-boot within your service?
To achieve such an architecture, we use patterns and principles. A set of well-known principles are the SOLID-principles. How strict one should follow those principles is a personal matter everyone has to decide for her-/himself. My personal opinion is that a pragmatic approach is often sufficient.
I also want to pick up #chrylis comment on abstraction. We as software engineers like to indulge ourselves in technicalities and create a superawesome abstraction that can basically deal with everything. But that is not the point. It does not have to deal with everything, only with what it will be used for. If you work for clients: that is not what the client is paying you for. And abstraction always comes at a cost. In most cases, this cost is complexity and/or readability. Or in words from wo*men wiser than me: KISS and YAGNI
Adding #Component to your class forces anyone who uses your class to know about Spring (i.e. spring is a compile time dependency).
The easiest alternative is to create separate class annotated with #Configuration in your app, and let it handle creating your class a Spring bean.
For example:
#Configuration
public class MyConfiguration {
#Bean
public HttpService httpService() {
return new HttpService();
}
}
This keeps your HttpService class free from Spring dependencies (assuming it doesn't use any other Spring annotations such as #Autowired), but lets it behave as a Spring bean in your own application.
Note that your class still depends on RestTemplateBuilder, which itself is a Spring boot class, which means your class (and anyone who uses it) will require Spring.
Is creating objects by hand, i.e. using new operator instead of registering Spring bean and using dependency injection considered bad practice? I mean, does Spring IoC container have to know about all objects in the application? If so, why?
You want Spring to create beans for classes that :
you want/need to inject instance(s) in other beans
you need to inject beans (or dependencies) in their own instances.
you want them to benefit from Spring features (instantiation management, transaction management, proxy classes Spring empowered such as Repository/Interceptor and so for...)
Services, controllers or interceptors are example of them.
For example a controller may need inject a service or an interceptor.
As well as you don't want to handle the instantiation of these classes by implementing yourself the singleton pattern for each one. Which could be error-prone and require boiler plate code.
So you want all of these classes to be beans managed by Spring.
But you don't want to Spring create beans for classes that :
you don't want/need to inject instance(s) in other beans
you don't need to inject beans (or rdependencies) in their own instances
you don't need them benefit from Spring features
Entity, DTO, Value Object are example of them.
For example an entity never needs to be injected into another entity or in a service as a dependency because entities are not created at the container startup but are generally created inside a method and have a scope limited to the methods lifespan.
As well as you don't need Spring to create instances which the lifespan is a method. The new operator does very well the job.
So defining them as bean instances makes no sense and appears even counter intuitive.
Spring implements the Dependency Injection pattern. You should inject in the container of spring the beans that are going to be used in other classes as dependence to be able to work. Usually classes that implement interfaces are injected so that if you change the implementation, the classes that use that interface do not know about the change.
I recommend you read the post about the dependency injection of Martin Fowler.
Using new is not bad and you are just giving the IoC container the responsibility of using new under the hood. IoC will know about all the classes that you register with it. When using frameworks, it's even more important to think about the applications architecture, because a framework makes bad design as easy to implement as good design.
If you don't need multiple implementations of a class, then use new.
If you think it's plausible that you may need to switch between implementations, consider your app design and find a suitable injection point so that refactoring won't be such a drain.
If you need multiple implementation of a class, then use a design pattern like a factory or a DI framework.
Not every nook and cranny of an application needs to be highly configurable. That's what leads to over-engineered and hard to maintain code.
Our java spring app exposes a Rest API and is fairly typical
It is build in layers:
RestController classes
Service classes
Repository classes
oracle DB
Those layers use the annotation #RestController, #Service, etc. with #Autowired to access the lower level.
Now, all those end up being singletons. But since there is no state, it should not be a problem.. Multiple requests can proceed concurrently using the same singletons objects (in different threads of execution). At least, that's my understanding.
Now, for one of our new Rest API endpoints, we have to call a third party API, so the datapath will be like this:
RestController
Service
CustomRestClient
third party server somewhere
In CustomRestClient, there is an #Autowired RestTemplate instance. Because everything is a singleton, this rest_template will be one as well.
Now i checked and it is thread-safe so it should work without any concurrency access exception. However I wonder:
Will that constitute a bottleneck, all parallel requests having to wait to use this one shared RestTemplate? with some internal locks or something? How to make sure no thread has to wait?
(btw one reason rest_template is autowired is to help with mock unit testing)
I guess my question is more about how to make sure this Spring singleton architecture can serve lots of parallel requests even when one layer has to use an injected object that may have state? And if that's impossible and that object has to be instantiated with "new", how can we still unit-test the class using the mock approach?
we have a frontend application that that uses Swing. We use Spring framework, but currently it is used just to autowire few beans...
What are reasonable next steps to use Spring more often?
Is it worth for non web application?
What would be advantages and disadvantages?
The advantages of using Spring (or any other dependency-injection) framework, is that you get a (hopefully) loosely coupled system, i.e you classes does not create instances of their collaborators, so you can easily change the implementation.
This is widely known as the Inversion-of-control principle (IoC, also the I in SOLID), and this is a good principle to follow. This means that spring is not limited to web applications, but can be used in any application that want to use an IoC-container (which is basically what spring-core is).
Disadvantages:
This really depends on how you look at things. There is more code (you have to define a entry-point for the injected collaborators), but that also makes the code more testable (the entry-points are seams which you can use to inject mocks and stubs in testing).
Also, you can't look at the code and immediately see which implementation of the collaborators that are used. But that also makes for good code, since you depend on interfaces, not implementations.
You get more config: either in an xml-file (old-style spring), or with annotations. Up until recently you had to rely on non-standard spring annotations to inject (#Autowired) resources, but now you can use the standard java dependency injection annotations, which means that you can switch out spring as your IoC-container without changing your code.
There are probably alot more advantages and disadvantages to using spring in your application, but this should get you started on deciding if using Dependency Inversion is a good thing for your application
More to the point of your question about Swing and Spring. In an application I have been working on we have been using spring to wire up the whole application. The different dialogs get their logic injected (no application logic should (in my opinion) be located together with gui logic). We are using JPA/hibernate as the database-layer, so we use spring spring to create and inject the entitymanager to our DAOs, and set up transactional settings.
I've written swing UI's that are backed by spring.
cons
the startup can be slower but you have to have a large app for that to happen.
and a splashscreen is a good idea in those situations.
its easy to "overbean" or over-zealously make everything a bean, which gets messy.
pros
spring works fine behind a GUI.
it provides a lot of services you can use
the obvious dependency injection and decoupling
a global event system, simpifying some of your own event listeners, for events that will only ever be fired by one source
resource accessing
database access is eays in 2 tier apps
rpc for 3 tier apps is easy
There are other services the spring application context provides, but that I haven't used.
If you go this direction, also look into the java-based configuration for spring, which is new in 3.0. I find that helpful as well, as it makes my spring configuration type-safe.
One disadvantage of using Spring in a Swing application is that Spring DI will make startup slower.
well one would be , if you ever decide to migrate to a web app , all you need ( well almost) to change would be the views. That's the beauty of MVC applications.