Spring - dependency injection - testing with different implementation - java

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.

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.

How to share Repository and Service classes between 2 projects

I am working on 2 projects, one web app (Spring MVC) and one standalone backend service application (Spring boot) that heavily interact together. I am using hibernate for both and they are both coded using the Netbeans IDE.
My "issue" is that i end up with duplicate code in both project, mainly in the Repository and Service layers. My entities are obviously also duplicated since both projects use the same database.
Is there a way to make some sort of class library (a third project maybe?) and put all the common code in there? If that is indeed possible, how do you then change each project so they can still access this code as if it were part of them? I was thinking of putting all my Repositories, Services and entities in there to avoid code duplication and greatly reduce the risk of error.
Thank you!
Separate those Repository and Service classes to a submodule.
The structure looks like:
-- your app
-- api (dependent on `common` module)
-- webapp (dependent on `common` module)
-- common
Then the problem is to initialize beans inside common module. AFAIK, you have two options:
In #Configuration class of api or webapp module, add base packages of common module to component scan packages
In api or webapp resources folder, add Spring configuration factory
/src/main/resources/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=your.path.AutoConfiguration
Define service/repository #Bean inside AutoConfiguration class
I am assuming in this answer your projects are connected to each other
You can set multiple properties within one Spring project, where you store your database connection parameters etc. with the help of multiple property files.
For example:
application-web.properties
application-backend.properties
You can use these in your project, by activating the needed properties file per application. The profile names will be web and backend in these cases.
When using maven, this is the command line I am using:
mvn spring-boot:run -Drun.profiles=<<profile>>
Now, back to your java code.
If there are classes only one of your application is using, you can specify this by 'profile'. Example:
#Controller
#Profile({ "web" })
public class WebEndpoint {
}
This way you can make the shared code available for both applications, without duplicating most of the code.

Java based dependency injection in Spring

I'm working in a webapp and this is the first time that I'm using Java based configuration. I have a bunch of class to configure all:
ApplicationContext
PersistenceContext
SecurityContext
WebAppInitializer
WebMvcContext
Now I'm defining Spring Data repositories and the service layer so I need to inject the repositories there. Normally I would use Autowired but I've read that it is preferable to define the injections manually so the question is, where?
Maybe neither of the previous configuration classes is suitable for such task but, do I have to create a single class to define all the injections or is better to have on for each function? What happens if the project grows too much?
I think that the main question would be what is best way to organize dependencies in a Spring project. What do you do?
I add here an image of the structure of the project as a petition. I'm trying to decouple layers and now I need to inject UserRepository to UserService.
No, I would not define a single class to do all the injections. All your classes are coupled that way.
I don't understand what "define the injections manually" means. You have to specify them in either XML or annotations. There's no other way that I know of.
You don't say if you're using XML or annotation configuration. I find myself using the latter more of the time, with only enough XML configuration to tell the Spring app context to scan for annotations.
The Spring idiom would have you specify your configuration in layers if you're using XML. It's a moot point for annotations, because they go into your source code.
Your application will read the Spring context on start up, instantiate all the beans, and wire together the necessary dependencies. You're good to go from then on.
I disagree with the link you provided. Avoid autowiring? No.
The article said that he recommends using XML configuration for large projects. This is a very small project at this point. It seems to me that auto wiring with annotations would be fine even by the article's author's words.

Resolve EJB Dependencies without a container

I am currently working on a solution for testing EJB 3 Services with JUnit.
(Yes, I have looked at ejb3unit but it doesn't work for me. Yes, I have looked at container-integrated testing with openEJB but that didn't work out neither..)
So my question is what would be the way for resolving #EJB annotated Dependencies? And I don't mean by using a DI Framework like Weld, Guice or Spring. The solution should be applicable for plain old JUnit Tests -> without using an EJB Container like JBoss, Glassfish or openEJB.
I was able to replace the injection of the entity manager via #PersistenceContext with a little hack using java reflections. So how would I do that for dependencies with #EJB annotation?
(I wouldn't mind building and resolving the dependency tree myself, just looking for ideas ;) )
Greetings from Germany,
p.s.
Not sure why you're against the solution you proposed.
I was about to offer stuff like Arquillian, but hey - you don't want to have a container involved.
I just want to be sure about the reason you don't want container, before I move on to some ideas (though I did not test them) -
With JBoss AS 7.x deployment time of enterprise application servers was vastly reduced,
Not to mention that with Arquillian you have a deployment API, and you can decide what you will deploy (i.e - deploy for example just a single bean for a given test).
However, I do respect you question, so here are some ideas -
A. You mentioned you managed to inject an EntityManager using reflection - how did you do that? Why not apply the same to your beans?
B. If you're encountering problems with A, why not develop your own injection code , based on cglib , for example (in order to create Proxy not just for interface, but also for classes).
This way, when an object of the class is created,
you will be able to intercept the default CTOR, and scan for fields annotated with #Ejb.
I would suggest using some sort of configuration file that maps for each bean interface how to instantiate an appropriate class, and run this flow recurisevely (as the injected bean might have a field with #EJB annotation as well).
Pay attention that if you decide to use this method of work, you'll be implementing some sort of "mini dependnecy injection framework" - besides the fact that personally I would be interested in seeing your code ( :) ) I think you should carefully think why you don't want to use an "already made solution.
Note regarding the Arquillian suggestions, that still requires an EJB Container like JBoss, GlassFish, or OpenEJB.
If the problem is just finding and including all the dependencies, try this jar that includes all the required dependencies for EJB Lite:
http://repo1.maven.org/maven2/org/apache/openejb/openejb-lite/4.0.0/openejb-lite-4.0.0.jar
Include that in your test classpath (no other jars needed) then just boot the embedded container:
EJBContainer container = EJBContainer.createEJBContainer();
MyBean bean = (MyBean) container.getContext().lookup("java:global/myModleName/MyBean");
Working example here
Have you look at Arquillian?
You can find all the documentation on the project page: http://www.jboss.org/arquillian.html

How to refactor a codebase that uses spring autowiring

I've inherited two fairly non-trivial codebases that uses spring for configuring the applications. Now I need to reconfigure the applications. But lots of the configuration is provided through autowiring so it is almost impossible to find out what the actual configuration is.
The projects are moderately sized, some 20-ish maven modules per project including integration test modules and such. Most modules define a few application contexts for various purposes, that contain one or two local spring config files along with one or two from the core modules it depends on. The result is a myriad of configurations, and that I cannot alter a class or variable name (or setter method) without risking breaking dependencies in some upstream or downstream module, even if no such dependency is visible anywhere in the project.
How do I work effectively with autowired dependencies in spring?
Can anyone, perhaps someone who actually likes autowiring, provide some insight into how you work with them effectively?
(I also inherited a small project that combines xml-files, autowiring and annotation-driven config, making dependency relations completely intractable, but I'll save those annotations for a separate question later)
You can perform re-factoring of auto wired beans using Intellij (I have version 9 Ultimate). Also Intellij has an option of making autowiring dependencies explicit. Link Provided below
http://blogs.jetbrains.com/idea/2009/03/making-spring-autowired-dependencies-explicit/
What IDE are you using? Spring STS (an Eclipse based IDE) has a lot of tools for working with Spring annotations and autowiring as well as good set of refactoring tools.

Categories

Resources