Spring 3 native compilation with multiple bean implementations for different environments - java

I have been evaluating the support of Spring Boot 3 for native compiling with native-image and so far I am very impressed. It has the potential to drastically reduce our cloud spend.
I note in the documentation, one of the major changes is the "closed world" assumption, meaning things like #ConditionalOn... are evaluated at build time rather than compile time.
To give a common example, I have an EmailSender interface and I have three implementations of this, for example LoggingEmailSender, SmtpEmailSender and SendGridEmailSender. Currently when running on the JVM the correct Bean for the environment will be created, LoggingEmailSender for local, SmtpEmailSender for test and SendGridEmailSender for production.
I am unsure what the best approach is to migrate this kind of conditional logic over to a Spring native way of doing things.
Currently the only option I can see would be to compile a binary per environment and use scopes at build and runtime to enable different implementations. This would result in a few different Docker images being created and deployed to their respective environments which breaks the previous conventions of promoting the same containers through various QA, Staging and then Production environments.
Is there a recommend strategy that I have overlooked or is this the best option available with the current level of maturity of native support?

As far as I know you can override properties for Spring Boot native applications too based on the run environment. And isn’t it possible you would rethink your bean creation a bit only. Drop the bean(s) conditional creation and have one create method for EmailSender only. In this method you should be able to create different implementations for this interface, it is interface right, based on property value you read too.

Related

In AEM how can I get project environment into my sling model

I need to use the environment in my sling model (dev|prod etc, not runmode such as author|publish). How can I inject it into my core model?
Is there any service for this ?
dev|prod etc, not runmode such as author|publish
author and publish are among the fixed run modes but run modes in general can be used to tell dev from prod (or similar kinds of environments) as well.
Usually, when AEM environments need to be told apart, e.g. dev vs prod, it is realised through custom run modes. While AEM as a Cloud Service places some limitations on just how much you can customise, the case you mention is still covered OOTB. Among other things, it can be used to manage environment-specific OSGi config.
An on-premise/hosted deployment gives you even more flexibility. I've always used customized run modes for this kind of purpose.
One thing to note is that it does raise an eyebrow that you need to programmatically check the run mode in a Sling Model. I'm not sure what you're implementing but if a piece of functionality is dependent on the environment, I'd rather handle it via alternative OSGi configuration assigned to a given run mode. I think it's generally easier to add another configuration as a sling:OsgiConfig node when required, as opposed to adjusting conditional logic in a Java class that only recognises a predetermined set of environments.
Provided that you have a set of run modes like this, you could inject SlingSettingsService into your model and read the run modes this way. Or you could write an OSGi service to encapsulate whatever logic you need. Such a service would start up with the configuration relevant to a given environment and you could inject it directly into your Sling model, knowing the values it returns are the ones you need.

Run multiple spring boot jars in one jvm

My project contains several services, each one is annotated with #SpringBootApplication and can be run on a random port via "gradle bootRun".
Is it possible to build the services into jars and run them together in one JVM? Not matter by programmatic method or just put them in a container.
Please show me some instructions if possible. Thanks!
It's a little hacky, but can be done. I wrote a blog post about it some time ago: Running Multiple Spring Boot Apps in the Same JVM. The basic idea is to run every Spring Boot application in a different classloader (because otherwise there would be resource conflicts).
I, personally, only used it for testing. I would prefer to run the different applications in different docker containers in production. But for testing it's pretty cool: You can quickly boot up your application and debug everything...
If you want to launch multiple spring boot microservices in single JVM then you can achieve this by launching multiple threads. Please refer sample code here https://github.com/rameez4ever/springboot-demo.git
Yes you can please check this SO.
However, if separating the running-user processes and simplicity is core , I would recommend the use of Docker containers, each running instance of the container(your apps) will runs in its own JVM on the same or distributed host
This is applicable, as David Tanzer said, by using two classloaders to start each Spring application in one JVM process. And no special code changes are required for these Spring apps.
In this way, almost every resource under those classloaders are separated: spring beans, class instances and even static fields of a same class.
But there are still concerns if you decide to hack like this:
Some resources like ports, cannot be reused in one JVM;
JVM system properties are shared within JVM process so pay attention if those two apps are reading a system property with same name. If you are using Spring, could try setting properties via command line argument to override those from system properties.
Classes loaded by the system class loader or its parents will share static fields and class definitions. For example, Spring Boot's thin jar launcher will use the system class loader to load bean class definition by default so there will be only one class definition even you have launched Spring apps in separate class loaders.

What is the state of the art tooling for Spring context analysis at runtime?

Assuming you have a rather big Spring application (including sources) at hand and you want to gather all kinds of information about the contexts beans at runtime : bean names, types, classes, child application contexts, property values, annotations, proxies structure etc.
What kind of tools would one use to find out ?
I used to maintain https://github.com/krosenvold/spring-context-analyzer, which detects problematic scope transitions. might need some adjudtments for spring versions >3
Looks like SpringSource is coming up with a solution called "Live Beans Graph" which is supposed to be shipping with STS 3.1. https://issuetracker.springsource.com/browse/STS-2810 has some details.

creating reusable modules

I'm writing a big Red5 Java application for the web.
Red5 a Flash Media Server alternative that is java based and is written with the spring framework.
I want to have many versions of my application online, each with different behaviors and different classes enabled or disabled.
I'm looking for a way to convert my code into modules based code that will allow me to remove/add modules/features from the main application.
I know about OSGI http://www.springsource.org/osgi but it says that it needs a SpringSource dm server and I have no idea how it's gonna work together in red5 and it's seems very complicated to fully understand.
I don't have a good knowledge of spring framework in general, i work with it db-related and that's it. red5 uses it more extensively.
so can anyone please make any sense from this information ? is there something that can be done to divide my code to modules ?
any information regarding the issue would be greatly appreciated.
My preferred method of dealing with this kind of situation is Dependancy Injection (DI). Spring has a DI capability built in, for which a tutorial is easy to find online. However, Spring's DI is not as good, for many reasons, as that provided by Guice, which I would highly recommend. (The main advantage of Guice over Spring's DI in my opinion is type safety.)
DI is basically a mechanism for replacing class implementations at runtime. Rather than hard code dependancies into classes (by having a class construct other classes directly for example) you code them to have their dependant classes passed to them in their constructors. The DI framework will then pass the correct instances at runtime according to the configuration. Spring configuration can be done via annotations or an XML file, Guice uses a subclass of com.google.inject.AbstractModule.
So you could use different configuration files for the different instances of your application, and have them provide different sets of features for activation, or indeed different implementations of the same feature. If you set up the application to use this technique then the only thing that need differ between instances is a single configuration file.

Spring annotation-based DI vs xml configuration?

Recently in our team we started discussing using spring annotations in code to define spring dependencies. Currently we are using context.xml to define our dependencies. Would you give me some clues for either approach, and when one is better to be used?
Edit: I know this seems a duplicate question to a more-general one, but I am interested in the impacts of annotations vs configuration for dependency injection only, which I believe would have different answers and attitude than the general question.
After reading some related posts here and having further discussion in the team we come to the following conclusions. I hope the would be useful to others here.
About XML configuration (which we are using up to now), we decided to keep it for dependencies defined by libraries (regardless if being developed by us, or by third parties).
Libraries, by definition, provide a particular functionality and can be used in various scenarios, not necessarily involving DI. Therefore, using annotations in the library projects we develop ourselves, would create a dependency of the DI framework (Spring in our case) to the library, making the library unusable in non-DI context. Having extra dependencies is not considered a good practice among our team (an in general IMHO).
When we are assembling an application, the application context would define the necessary dependencies. This will simplify dependency tracking as the application becomes the central unit of combining all the referenced components, and usually this is indeed where all the wiring up should happen.
XML is also good for us when providing mock implementations for many components, without recompiling the application modules that will use them. This gives us flexibility when testing running in local or production environment.
In regards to annotations, we decided that we can benefit using them when the injected components will not vary -- for instance only a certain implementation for a component will be used troughout the application.
The annotations will be very useful for small components/applications that will not change or support different implementations of a dependency at once, and that are unlikely to be composed in a different way (for instance using different dependencies for different builds). Simple micro-services would fit in this category.
Small enough components, made up with annotations, can be used right out of the box in different projects, without having the respective applications to cover them in their XML configuration. This would simplify the application dependency wiring for the application and reduce repetitive setups.
However, we agreed that such components should have the dependencies well described in our technical documentation, so that when assembling the entire application, one can have an idea of these dependencies without scrolling through the code, or even loading the module in the IDE.
A negative side effect of annotation-configured components, is that different components could bring clashing transitive dependencies, and again it is up to the final application to resolve the conflicts. When these dependencies are not defined in XML, the conflict resolution approaches become quite limited and straying far from the best practices, if they are at all possible.
So, when going with annotations, the component has to be mature enough about what dependencies it is going use.
In general if our dependencies may vary for different scenarios, or a module can be used with different components, we decided to stick to XML. Clearly, there MUST be a right balance between both approaches, and a clear idea for the usages.
An important update regarding the mixed approach. Recently we had a case with a test framework we created for our QA team, which required dependencies from another project. The framework was designed to use the annotation approach and Spring configuration classes, while the referenced project had some xml contexts that we needed to reference. Unfortunately, the test classes (where we used org.testng with spring support) could only work with either the xml or java configuration classes, not mixing both.
This situation illustrates a case where mixing the approaches would clash and clearly, one must be discarded. In our case, we migrated the test framework to use spring xml contexts, but other uses could imply the other way around.
Some advantages of using XML configuration:
The XML configuration is at one place, instead of being scattered all over the source code in case of annotations. Some people may argue that IDEs like STS allow you to look at all annotations based configuration in one place, but I never like having dependencies on IDEs.
Its takes a little more efforts to write XML config, but it saves a lot of time later when you search for dependencies and try to understand the project.
XML keeps configuration well organized and simple. Hence is easier to understand, it helps new relatively inexperienced team members get up to speed quickly.
Allows you to change the config without a need to recompile and redeploy code. So it is better, when it comes to production support.
So in short XML configuration takes a little more efforts, but it saves you a lot of time & headache later in big projects.
2.5 years later:
We use annotations mostly these days, but most crucial change is that we create many small projects (instead of a one big project). Hence understanding dependencies is not a problem anymore; as each project has it's unique purpose and relatively small codebase.
from my experience, I would prefer(or rather am forced by limitations) to use a combination of XML and annotation based DI . If I need to inject a Map of elements inside a bean , I would have to define a util:map and autowire it . Also, I need to use XML DI to inject datasource into the sessionFactory if I have multiple datasources and so on . So a combination of both would be requited .
I prefer the usage of component-scan to autodetect the services and Dao . This cuts down a lot of Configuration (We cut down the configuration files by around 50% switching to component-scan). Annotation based DI supports both byName(#Resource) and byType(#Autowired).
In short my advice to be to go for a fixture of both . I feel that more annotation support will definitely be on cards in future Spring releases.
Take a look at this answer here: Xml configuration versus Annotation based configuration
A short quote directly from there:
Annotations have their use, but they are not the one silver bullet to
kill XML configuration. I recommend mixing the two!
For instance, if using Spring, it is entirely intuitive to use XML for
the dependency injection portion of your application. This gets the
code's dependencies away from the code which will be using it, by
contrast, using some sort of annotation in the code that needs the
dependencies makes the code aware of this automatic configuration.
However, instead of using XML for transactional management, marking a
method as transactional with an annotation makes perfect sense, since
this is information a programmer would probably wish to know.
EDIT: Also, take a look at the answers here: Java Dependency injection: XML or annotations They most probably target the area of your interest much better.
From my own experience annotations better than xml configuration. I think in any case you can override xmls and use annotations. Also Spring 4 give us a huge support for annotations, we can override security from xml to annotations e.t.c, so we will have not 100 lines xml but 10 lines Java Code.
Are annotations better than XML for configuring Spring?
The introduction of annotation-based configurations raised the
question of whether this approach is 'better' than XML. The short
answer is it depends. The long answer is that each approach has its
pros and cons, and usually it is up to the developer to decide which
strategy suits them better. Due to the way they are defined,
annotations provide a lot of context in their declaration, leading to
shorter and more concise configuration. However, XML excels at wiring
up components without
touching their source code or recompiling them. Some developers prefer
having the wiring close to the source while others argue that
annotated classes are no longer POJOs and, furthermore, that the
configuration becomes decentralized and harder to control.
No matter the choice, Spring can accommodate both styles and even mix
them together. It’s worth pointing out that through its JavaConfig
option, Spring allows annotations to be used in a non- invasive way,
without touching the target components source code and that in terms
of tooling, all configuration styles are supported by the Spring Tool
Suite.
my personal option is that xml is better since you have all at one place and you do not need to deep into your packages to search the class.
We can not tell which method is good, it depends on your project. We can nither avoid xml nor annotation. One advantage of using xml is that we can understand the project structure just seeing the xml context files, but annotation reduces lots of meta configuration. So I prefer 30% xml and 70% annotation.
By using XML, you prevent code from being polluted with framework-specific annotations and thus creating an undesired coupling. Keep the framework at the application boundary so you can always replace it should the need arise.
Frameworks come and go, but many applications live for decades. Fortunately, Spring is a non-invasive framework and doesn't bend your architecture. Keeping the configuration in XML will make it even more detached from your application.
Remark: in order to benefit from all this, your application should be well-designed in the first place.

Categories

Resources