I have a large application with a database, Swing UI etc. Now I want to add a REST API for this application. Spring Boot allows easy generation of a REST API with useful features such as OpenApi documentation and authentication.
However when I run the Spring Boot application from within the large non Spring Boot application the Spring Boot application gets confused by the dependencies of the parent application and fails to run.
So my requirement is this: run a Spring Boot application from withing a non Spring Boot application without dependency interference from the parent application. I am currently running the Spring Boot application by adding the executable jar as a dependency and then calling
org.springframework.boot.loader.JarLauncher.main(new String[0]);
to run the Spring Boot application. I am not set on this way of doing it and any suggestions will be greatly appreciated.
Spring is a huge collection of highly configurable software libraries that can be used to setup (among other things) REST API endpoints and OpenAPI documentation and UI.
Spring Boot is a project to simplify the process of using these libraries by applying an opinionated view of how to run them within a standalone process.
By asking how to run a Spring Boot application within a larger application you are trying to get the benefit of the opinionated setup while violating the assumptions that the setup is based on. I guess in theory it might be possible using some sort of handrolled classloader isolation, but once you've solved the dependency problem you'll probably end up with class version conflicts, issues with configuration locations, etc. In short if it is possible at all the effort of doing so would negate the benefit.
There are two ways of resolving the issue.
Use Spring Boot to build your API as a standalone process. Configure the new process to talk to the same database as the existing application. If neccessary factor out any code common to both the existing application and the API (JPA entities, DAO classes etc) into a shared library. If you go with this option you will have the overhead of having to manage multiple kinds of process in your production environment, which is more complex - but has advantages in terms of decoupling scaling, release cycles, restart times. See the debate on microservices (https://martinfowler.com/articles/microservices.html).
Use the Spring libraries that provide REST and OpenAPI features as part of your existing application, without using Spring Boot. You'll need to have SpringMVC set up in order to use #RestController annotated classes. If your existing application is a web application that's not too bad (https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/mvc.html). If it's not run in a webserver already you'll have to launch the SpringMVC framework in an embedded webserver (https://devcenter.heroku.com/articles/create-a-java-web-application-using-embedded-tomcat). There's a good article on adding OpenAPI to an MVC application here: https://www.baeldung.com/spring-rest-openapi-documentation.
you can simply exclude auto-configure dependencies. Here is an informative link https://www.marcobehler.com/guides/spring-boot
Here is a code snippet of how to exclude when applications get started.
#SpringBootApplication(exclude = {DataSourceAutoConfiguration.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(PayPalApplication.class, args);
}
}
or the other ways
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
I want to share another Spring Framework dependencies https://www.marcobehler.com/guides/spring-framework
Related
Hi folks need some opinions here.
I already have a spring boot application holding all my rest APIs running on tomcat that ships in with spring-boot-starter-web.
I would like to set up jobs using spring batch that will be schedule via kubernetes. The idea is to share the same business logic instead of creating a standalone batch project which i need to maintain double business logic.
Question, scheduling via kubernetes meaning i will be firing java -jar someJar --spring.batch.jobNames=xxx in container, doing that it will also start up all my RestApis right? which in turn unnecessary and waste of resources. Anyway to mitigate this or my understanding is wrong?
The way I would implement this is by extracting the common business logic in a separate module, and make the batch app and the webapp depend on that module.
I'd like to write a framework on top of spring boot that does a bunch of things, like exposing specific endpoints and doing specific logic.
But I'd like to build it as a framework in the sense that someone else can take it, implement a number of specific interfaces and it will then run as a spring boot web application.
I haven't found how to do this specifically.
I've looked into this article about writing a custom starter, but it looks like the dependency is the wrong way round. I want the custom code "plugged into" the framework rather than calling the classes of the starter directly, if that makes sense.
It seems you're looking for the EnableAutoConfiguration plugin. This is the core of any spring boot libraries that wants to deal with spring boot custom beans without user help. EnableAutoConfiguration classes need to be placed in spring.factories file.
spring.factories file can have multiple classes each class needs to be provided using org.springframework.boot.autoconfigure.EnableAutoConfiguration=A,B,C
Using these boot classes you can create many beans that could be the backbone of your framework. Also if you want to provide custom properties as boot does, you need to add those properties file spring-configuration-metadata.json file.
For your reference, you can see this repo Rqueue
Background
I have built a console java application using kotlin and gradle.
The gradle file creates a fat jar which I can run from the command line using
java -jar <project>.jar
The jar contains the application.properties file from which properties are read.
Problem
I would like to specify on the command line that the application.properties file should be read from some external path.
When using spring boot, I have used
java -jar -Dspring.config.location=somepath/application.properties <project>.jar
and this works.
But it does not seem to be working in the non-spring boot application
Question
Is it possible to specify external configuration on the command line for non spring boot applications?
Spring boot has a whole chapter in the documentation which deals with various ways of configuration.
Obviously if you don't have spring boot you should implement something similar to it by yourself.
First thing you should decide - at which level you need the configuration to be integrated into your application:
Do you only want to read the key/values from command line or maybe rely on environment variables or system properties?
In general, what is the source of your configuration: Yaml? Properties file? maybe consul or etc.d?
Do you want to create a java object that reflects the configurations that you've read (like classes annotated with #ConfigurationProperties in spring boot do?
Do you want to support only one source of configuration or you want the various sources of configurations to be supported?
If you ware using Spring, do you want configuration properties to be automatically injected into beans?
If you're planning to use properties/yaml (like application.properties in spring boot) - where do you want to place them? Non spring boot application won't read them "auto-magically", you'll have to implement this logic.
Are you planning to deal with profiles (non-spring-boot application still supports flavors of loading different beans depending on specified profile).
Spring boot has answered all these questions and more.
Here are some options that you might want to give a try to if you're running outside the spring boot context but still have spring application:
Since spring 3.1, I guess, there is a#PropertySource annotation that you can use to make spring load properties from the file in the classpath or some "place" in the filesystem. This article summarizes the usage of this method as well as compares what spring boot has up on its sleeves as opposed to regular spring application. This is also a nice tutorial that covers regular spring features.
Something out of spring eco-system but still can be useful: apache common configuration project. There are some workarounds to integrate it with spring application, see here
Considering all the answers here I concluded that though it is possible to enable external configuration in applications that are not spring boot, it does require some effort.
Therefore I decided to use Spring Boot in the container.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
So the project I want to convert is at https://github.com/zhongjis/keyword_search_engine_xlsm.
This program intends to build a search engine based on the user input files (xlsm). It extracts content from an XLSM (excel) file first and stores them to the DB. while building up the database, the program will also calculate some special numbers such as td-idf which will be used later for result ranking.
Current technology used:
Gradle
Java 13
MongoDB
What I am trying to do?
convert this console application to a full-stack web application that uses Spring Framework. which means that I want to add a GUI.
I am trying to keep as much original code as possible during this transition. For me, it is ok to modify them to fit the MVC design.
In one sentence, I want to make my current application runs on the Spring framework. it is OK only to have console output.
What are my questions?
even though I did a lot of research on Spring Framework (especially Spring boot). But I am still struggles with what should I do first in order to implement the framework. I would like some suggestions on how to start (or what should I change on my original project). All I learned from the internet is adding various dependencies to build.gradle. But I still have no idea what to do next. Should I start a new Web Application from scratch or try to convert the current one?
Thank you
I tried my best to fill in details. However, this post might still be vague or confusing on some parts and need some clarification. Please feel free to let me know and I am more than willing to do that :)
It appears that you want to create a Web Application.
The easiest way to get started is to use Spring Boot, which is the 'opinionated' version of Spring, meaning that it uses smart defaults. You should start by using the Initializer to generate your project: https://start.spring.io/. Keep generating and testing until you get what you want.
The simplest method is to build an executable JAR, which will contain your web server and can be run anywhere you have Java. This is the default setting on Initializer site above. My advice: Accept Spring Boot defaults until you know what you're doing.
GUI:
The simplest method is to use Thymeleaf templates to display your HTML.
Controller:
Learn how to write a basic controller to return a Thymeleaf template. The simplest way to begin is with standard HTML posting to your controller.
Docs
A great strength of Spring is the ample documentation.
See: https://spring.io/guides/gs/serving-web-content/
and: https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html
I'd suggest you start with Spring Initializr to bootstrap a fully working Spring Boot application. Alternatively, you can use JHipster(https://www.jhipster.tech/) which will create a Spring Boot app AND a front-end for you which you may prefer.
Create a base application
https://start.spring.io/
Select the dependencies you need such a MongoDB:
Build out basic components
So the basic flow in a Spring Boot App is Controller -> Service layer -> Repository.
The Controller will allow you to create REST endpoints annotated with #RestController:
https://spring.io/guides/gs/rest-service/
Then put your business logic from your util package into a service class annotated with #Service.
https://medium.com/stackavenue/why-to-use-service-layer-in-spring-mvc-5f4fc52643c0
You will autowire your Service layer into the Controller using a #Autowired annotation.
Then create a Spring Repository for database operations:
https://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html
Then #Autowire your Repository into your Service layer.
In summary, the whole flow is your front-end(Angular, ReactJS etc.) makes a HTTP call to your Spring App which is handled by the Controller which calls the service layer which calls the Repository to perform database operations.
Building a Front-end
You can use Angular for this. A lot of front-end devs prefer React but for a new user, Angular is a more holistic framework in my opinion. https://cli.angular.io/
Install npm(https://www.npmjs.com/get-npm)
Then do the following to get a fully functional Angular app up and running:
npm install -g #angular/cli
ng new my-dream-app
cd my-dream-app
ng serve
Then you can use the Angular HttpClient to make a call to your Spring Boot service: https://angular.io/guide/http
This repo is a couple years old but it contains a full-stack Angular/Spring Boot app that you can check out for reference: https://github.com/anataliocs/Exercise-files-full-stack-app-angular-spring-boot.
You could use Thymeleaf as well(https://spring.io/guides/gs/serving-web-content/) but most modern Full-stack web apps use a separate front-end app such as Angular, React(https://reactjs.org/), Vue.js(https://vuejs.org/) etc.
JHipster
Jhipster will do all this and also hook up a fully working front-end for you. https://www.jhipster.tech/
Courses
I also have full courses on building full-stack apps on LinkedIn learning, but full disclosure, it's not a free service but there is a 30 day trial.
Full-stack app with Angular and Spring Boot
Full-stack app with
JHipster
I will suggest the same as KevinB use SpringBoot/Thymeleaf for easy MVC style application to minimize using too many technology stack.
But before you jump into action remember any migration of project/application into new framework or architecture first needs breaking down the components (source as well as target and then mapping them).
The github project utilizes MONGODB which you would not need to re setup.
You can do the migration in 2 ways, based on functionality i.e build all of backend and front for a functionality at a time
or develop mock rest end points first and then do the UI making call to service end points in spring boot.
I have two Spring applications which interact which each other via database and some AMQP:
web-application built on Spring MVC
Spring-Boot application
Each application has its independent context and properties files.
What is the proper way of writing single integration test for these two applications?
More specifically: I can merge this two applications in one maven project in order to have access to both of them.
Is it possible to configure test contexts for both applications in
one Spring test? At the moment I have no idea how to tell spring use different contexts for different applications in one test.
Another purpose of this testing is also to obtain code coverage for these two applications. That is why I can not just start, say, Spring-boot application as separate process. Is it possible at all?
Spring's test module brings up a single application context (take a look at the key abstractions section of the official documentation) per test so no, you cannot have multiple application contexts per test.
What you can have is a merged application context that imports both the Spring Boot and Spring MVC application's context; that way, you can test beans from both applications. However, this is probably not what you want to do and it's something I would recommend against - your tests will become almost worthless since making this approach work could probably entail some hacks and you will not be testing your applications realistically given that they will be deployed separately.
You should write per-application integration tests and measure coverage for each of them. If your application is relatively small, you can have an end-to-end testing module that would leverage Docker containers to create an environment similar to your production and verify that your applications correctly work together.