Can Spring Boot be used with OSGi? If not, any plans to have an OSGi Spring Boot? - osgi

Can Spring Boot be used with OSGi? If not, any plans to have an OSGi Spring Boot (Apache Felix or Eclipse Equinox)? In my opinion, cloud applications must be highly modular and updatable like OSGi offers.

Yes, it's possible to run Spring Boot apps in OSGI container.
First of all, you'll have to switch from Spring Boot jar packaging to OSGI bundle.
If you're using Maven you can use org.apache.felix:maven-bundle-plugin for doing that.
As Spring Boot dependency jars are not valid OSGI bundles, we should either make them valid bundles with bnd tool or we can embed them into the bundle itself. That can be done with maven-bundle-plugin configuration, particularly with <Embed-Dependency>.
However, we need to start the bundle with Spring Boot app somehow. The idea is to start Spring Boot in BundleActivator:
#Import(AppConfig.class)
#SpringBootConfiguration
#EnableAutoConfiguration
public class SpringBootBundleActivator implements BundleActivator {
ConfigurableApplicationContext appContext;
#Override
public void start(BundleContext bundleContext) {
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
appContext = SpringApplication.run(SpringBootBundleActivator.class);
}
#Override
public void stop(BundleContext bundleContext) {
SpringApplication.exit(appContext, () -> 0);
}
}
You should also set context classloader to an OSGI classloader loading the bundle by Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());.
That is required because Spring uses context classloader.
You can see this in action in my demo repo: https://github.com/StasKolodyuk/osgi-spring-boot-demo

I think it worth posting as separate answer (not everyone reads all comments to answers).
Excellent solution from #StasKolodyuk gives a way to run Spring Boot application in an OSGI environment.
But with limitation: Spring Boot's auto-mapping by annotation does not work because of lack of package scan support when run in OSGI.
Here is another trick, that finally allows Spring Boot app with components to be auto-taken from your code to be run in OSGI (I tested in Karaf).
Functional example is available at https://github.com/dimmik/osgi-spring-boot-demo
The trick is to provide appropriate ResourcePatternResolver to SpringApplication instance:
package by.kolodyuk.osgi.springboot;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.osgi.io.OsgiBundleResourcePatternResolver;
#SpringBootApplication
public class SpringBootBundleActivator implements BundleActivator {
ConfigurableApplicationContext appContext;
#Override
public void start(BundleContext bundleContext) {
// Set context classloader (main trick, to enable SpringBoot start at the first place)
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
// trick to enable scan: get osgi resource pattern resolver
OsgiBundleResourcePatternResolver resourceResolver = new OsgiBundleResourcePatternResolver(bundleContext.getBundle());
// and provide it to spring application
appContext = new SpringApplication(resourceResolver, SpringBootBundleActivator.class).run();
}
#Override
public void stop(BundleContext bundleContext) {
SpringApplication.exit(appContext, () -> 0);
}
public static void main(String[] args) {
SpringApplication.run(SpringBootBundleActivator.class);
}
}

One possibility is to embed OSGi into your Spring Boot Application, to make some parts of your application accessible through the framework. See https://stackoverflow.com/a/4673904/173101 to see how you can start OSGi programmatically.
But in general there is nothing like "OSGi-Support". OSGi can be integrated into every Java-Application and, vice versa, you can package every Java-Code (also your Spring-Boot application) into an OSGi-bundle to start it within an OSGi container (although it probably wouldn't make much sense at all).

There's actually plenty of good reasons for deploying Spring Boot into OSGi, the main one being performance, particularly startup performance if your Spring Boot service is a functional service (i.e. it starts, returns results, ends). An application I'm currently beta testing in Spring Boot starts up in ~ 0.5 seconds deployed to Equinox versus 3.5 seconds on its own. Other reasons might be integration to an OSGi based application or Java EE server.
That said, you can also run OSGi from Spring Boot, for performance reasons I would probably favour Concierge as an OSGi implementation over Felix or Equinox, simply due to its small size (unless your app needs all the features of the bigger implementations.
Another alternative would be to wrap the Spring libraries used by your Spring Boot application into MSF4J (from WSO2). This doesn't take much work and can give you a 10x faster startup with 1/10th the memory usage.

No, it doesn't support OSGi. Spring Boot is aimed to create microservices as packaged applications with every dependency and even the servlet containers packaged in an executable JAR, so it's highly modular and updateable, without the need to provide and configure an OSGi container.

Spring boot - well typical spring boot apps, are a little "fat" for osgi... if you are using the starter-web or jersey you'd need to add some sort of port determination scheme since ports are shared by all osgi "services" the system that the osgi runtime lives on.
The reason I would recommend avoiding spring-boot unless you can pare it down is the spring boot fat jar / war you create launches a sub class loader. This doesn't simplify things when you get confused about standard osgi class loader issues (com.whatever.someobject.MyClass not being the same in different bundles and classloaders because they are not "imported" from the same bundle that exports to all others) if there are any requirements for interbundle service communication.
I would suggest following guides to pare down to "spring boot core" if any exist you don't need the web listener and avoid all inter-bundle service interfaces that use any objects that aren't part of the standard imports (like core java se classes etc..). You only care about lifecycle right?

Why not stick to the microservice patterns and just launch your OSGI app as a separate application communicating with your spring-boot services over their REST API.
On the OSGI application side you can use Jetty / Jersey etc to easily manage REST communication

Related

Include a REST API in Vaadin war app without using Spring boot

I have a Vaadin (v23) app deployed as a war that provides a UI to other wars running in the same Tomcat instance. I now have a need to expose a couple of public endpoints in the Vaadin app via a REST API, but all of the examples I've found assume an app built on Spring-boot, which this isn't. Is there any way of adding a simple, public API to the Vaadin app without having to resort to rebuilding it as a Spring-boot application?
I using tried spring-webmvc with #RestController and overriding startup configurations, but all attempts to navigate to the API are ignored.
Thanks for the helpful comments. I ended up doing it the old-fashioned way, via a static inner class of my MainView:
#WebServlet("/api/*")
public static class CustomFormServlet extends HttpServlet {
...
}
It's an inner class to share some things with MainView. I'm sure there's better ways, but it works and it's only to serve a couple of public endpoints.

Accessing google Guice based services in spring boot application

I have services developed using Google guice DI framework and I want to inject them in spring boot application. Could anybody thro some light on how we can access the google guice based services in spring boot application? Any pointers to any sample code?
Welcome to StackOverflow!
There are two different things that you could do, depending on what you actually did in the Guice services.
If you used only JSR330 annotations, then you could theoretically simply replace Guice Modules with Spring #Configuration classes and just use Spring to do the D.I. This would work because both Spring and Guice support the JSR330 annotations. In my view, this can work in only fairly simple cases.
Use the org.springframework.guice:spring-guice library from Spring. It allows you to use Guice Modules and the provided beans.
First you need to include it in your pom:
<dependency>
<groupId>org.springframework.guice</groupId>
<artifactId>spring-guice</artifactId>
<version>1.1.3.RELEASE</version>
</dependency>
Then you must configure Spring to use the needed Guice Modules:
#Configuration
#EnableGuiceModules
public static class GuiceConfig {
#Bean
public MyModule myModule() {
return new MyModule();
}
}
You can read more on the GitHub for this project: https://github.com/spring-projects/spring-guice#using-existing-guice-modules-in-a-spring-applicationcontext.

Would #WebService annotation interfere with #Endpoint in Spring Web Services?

I'm writing a Spring Boot Web Services application, thus I'm using #Endpoint and #PayloadRoot annotations.
For documentation purposes I'm using Enunciate, which doesn't support Spring-WS annotatinos at the time of writing.
Would it do any harm if I add the javax.jws.WebService to an already #Endpoint-annotated class too? Should I use only one of them?
As long as you don't have a JAX-WS implementation like CXF in your classpath and configured the WebService annotation will not be considered.

Migrating Spring web application to Spring Boot

I have a web project, and I depoly it on tomcat easily. Infact I have a WebAppInitializer class that implements WebApplicationInitializer (this class it's really fat), as you know every application server that supports servlet 3.0, it can easily detect it and try to boot it. Now I wonder that it could be possible to use spring boot starter and without any further configuration, I pass my WebAppInitializer to it and spring boot based on my WebAppInitializer boots my project?
I just want to use the approach of spring-boot to deploy application on Tomcat and I don't want to use other spring-boot's facilities.
Yes, it's an old question. But I do not see an accepted answer and the one closest to a working one only has a link to an external resource. So here it is.
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-embedded-container-context-initializer
28.4.2 Servlet Context Initialization
Embedded servlet containers do not directly execute the Servlet 3.0+
javax.servlet.ServletContainerInitializer interface or Spring’s
org.springframework.web.WebApplicationInitializer interface. This is
an intentional design decision intended to reduce the risk that third
party libraries designed to run inside a war may break Spring Boot
applications.
If you need to perform servlet context initialization in a Spring Boot
application, you should register a bean that implements the
org.springframework.boot.web.servlet.ServletContextInitializer
interface. The single onStartup method provides access to the
ServletContext and, if necessary, can easily be used as an adapter to
an existing WebApplicationInitializer.
Scanning for Servlets, Filters, and listeners
When using an embedded
container, automatic registration of classes annotated with
#WebServlet, #WebFilter, and #WebListener can be enabled by using
#ServletComponentScan.
[Tip] #ServletComponentScan has no effect in a standalone container,
where the container’s built-in discovery mechanisms are used instead.
I've tried it. It works
In my use case I have project containing a few dozens of webapps, designed to run on Tomcat as WAR. Lots of logics was neatly crafted into WebApplicationInitializers and it seemed there should be an easier way to reuse all this. Adding implements ServletContextInitializer to those initializers and exposing them as beans through #Configuration classes lit my webservers up with SpringBoot's embedded Tomcat.
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-create-a-deployable-war-file describes precisely how to do it
From the Spring Boot docs:
Servlet 3.0+ applications might translate pretty easily if they already use the Spring Servlet 3.0+ initializer support classes. Normally all the code from an existing WebApplicationInitializer can be moved into a SpringBootServletInitializer. If your existing application has more than one ApplicationContext (e.g. if it uses AbstractDispatcherServletInitializer) then you might be able to squash all your context sources into a single SpringApplication. The main complication you might encounter is if that doesn’t work and you need to maintain the context hierarchy. See the entry on building a hierarchy for examples. An existing parent context that contains web-specific features will usually need to be broken up so that all the ServletContextAware components are in the child context.
So yes, it's possible but you need to convert it to SpringBootServletInitializer, which seems to be quite similar.

Difference between Spring and Spring Boot

There are many people who advised me to use Spring Boot instead of Spring to develop REST web services.
I want to know what exactly the difference between the two is?
In short
Spring Boot reduces the need to write a lot of configuration and boilerplate code.
It has an opinionated view on Spring Platform and third-party libraries so you can get started with minimum effort.
Easy to create standalone applications with embedded Tomcat/Jetty/Undertow.
Provides metrics, health checks, and externalized configuration.
You can read more here http://projects.spring.io/spring-boot/
Unfortunately and I mean this out of personal frustration with Spring boot, I have yet to see any real quantified list, where the differences are explicitly outlined.
There is only qualifications such as the rubbish sentence "...opinionated view..." which are bandied about.
What is clear, is that SpringBoot has wrapped up groups of Spring annotations into its own set of annotations, implicitly.
Further obfuscating, and making the need for anyone starting out in SpringBoot to have to commit to memory what a particular SpringBoot annotation represents.
My reply therefore is of no quantifiable benefit to the original question, which is analogous to that of the SpringBoot authors.
Those behind Spring IMO deliberately set-out to obfuscate, which reflects the obtuseness of their JavaDoc and API's (see SpringBatch API's as an example, if you think I am flaming) that makes one wonder the value of their open-source ethos.
My quest for figuring out SpringBoot continues.
Update. 22-08-2022
Read this (https://docs.spring.io/spring-boot/docs/current/reference/html/using.html#using.auto-configuration) and you will figure out for yourself what "opinionated" means.
There are over 140 Config classes that Springboot can use for this opinionated view, depending on what is on your classpath.
yes, on your classpath.
Finally and bizzarely, the annotation #SpringBootApplication is a configuration annotation as it includes it.
Go figure :=)
Basically, Spring Boot is an opinionated instance of a Spring application.
Spring Boot is a rapid application development platform. It uses various components of Spring, but has additional niceties like the ability to package your application as a runnable jar, which includes an embedded tomcat (or jetty) server. Additionally, Spring Boot contains a LOT of auto-configuration for you (the opinionated part), where it will pick and choose what to create based on what classes/beans are available or missing.
I would echo their sentiment that if you are going to use Spring I can't think of any reasons to do it without Spring Boot.
Spring Boot is opinionated view of Spring Framework projects.Let's analyse it through one program taken from Spring Boot Documentation.
#RestController
#EnableAutoConfiguration
public class Example {
#RequestMapping("/")
String home() {
return "Hello World!";
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Example.class, args);
}
}
It's a very basic REST API and you need to add Spring-boot-starter-web in your POM.xml for the same. Since you have added starter-web dependency, the annotation
#EnableAutoConfiguration guesses that you want to develop a web application and sets up Spring accordingly.
Spring Boot auto-configuration attempts to automatically configure your Spring application based on the jar dependencies that you have added. For example, if HSQLDB is on your classpath, and you have not manually configured any database connection beans, then Spring Boot auto-configures an in-memory database.
It's opinionated like maven. Maven creates a project structure for you which it thinks is the general pattern of projects like it adds src/main/java folder or resource folder for you.
Spring boot helps in faster development. It has many starter projects that helps you get going quite faster. It also includes many non functional features like: embedded servers, security, metrics, health checks etc. In short, it makes, spring based application development easier with minimally invading code(Less configuration files, less no of annotations).
Reference: https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-documentation-about
For developing common Spring applications or starting to learn Spring, I think using Spring Boot would be recommended. It considerably eases the job, is production ready and is rapidly being widely adopted.
Spring Boot is supposedly opinionated, i.e. it heavily advocates a certain style of rapid development, but it is designed well enough to accommodate exceptions to the rule, if you will. In short, it is a convention over configuration methodology that is willing to understand your need to break convention when warranted
For Spring Framework, you need to configure your project using XML configuration or Java configuration.
But for Spring Boot, these are preconfigured according to Spring team's view for rapid development. That is why Spring Boot is said to be an "opinionated view" of Spring Framework. It follows Convention over Configuration design paradigm.
Note: These configurations include view resolvers for MVC, transaction managers, way of locating container managed beans (Spring beans) and many more. And of course you can override any of these preconfigurations according to your need.
Spring Boot supports embedded servlet containers like Tomcat, Jetty or Undertow to create standalone applications, which Spring Framework doesn't.
Spring eliminate boilerplate code.
Spring-boot eliminates boilerplate configurations.
more

Resources