While my Spring Boot Rest application is already running, I want to be able to turn the Rest functionality on and off at will programatically without having to restart the application.
How do I go about doing so?
EDIT: When I say turn off Rest Functionality I literally mean that Tomcat stops listening on the port. And it starts listening on the port again when it's turned on.
I can see two possible solutions:
Close the port on the machine by creating a schedueled task that is responsible of opening and closing the port on specific times
In Spring terms, what you want to do boils down to a configuration change. SpringBoot provides a standard way to refresh configuration changes without having to restart your application. This is achieved by refreshable beans. What you can do is override the default Tomcat bean by a custom bean that is refreshable. Then you can create a task (through a CI, schedueled script ...) that will update the configuration (you can provide config as Env variables) and refresh the beans of the application.
The first solution is much easier. The second approach needs some more development inside your application.
Related
I referred this tutorial to restrict certain ip in jboss and Spring Boot application.
http://www.mastertheboss.com/jboss-web/jbosswebserver/how-to-restrict-access-to-jboss-web-application-by-ip-or-host
But the tutorial is not complete. Where should I place those codes? Are there any other methods to do that?
If any one know any other methods please mention that here. Thanks in advance.
IMO the Valves mentioned in tutorial are the ways to customize tomcat embedded into the Jboss application. Note that this tutorial is really old - from 2014, probably JBoss has changed since then.
I remember back that times JBoss indeed included Tomcat inside to handle the web requests, so probably there was some kind of server.xml of tomcat.
Now, there are other ways:
Place the application behind some proxy that would restrict the access. Probably its the best approach if your environment supports that.
Use filters inside the application. You can create a web filter and register it in spring boot application regardless whether its a Jar with embedded server or WAR that you're planning to deploy on JBoss. This can be really flexible but on the other hand it includes some java coding and will consume some resources of your application. You can use this approach if you don't have spring security in your application and you don't want to introduce one, otherwise read (3).
Kind of paraphrase on 2 but used with spring security, that has the filtering facility built in: here is how you can do that. Note that besides the actual Java code used for implementation, 3 and 2 are pretty similar.
I'd approach this problem in the following way:
If the IP where connections are accepted is subject to change, I'd configure reverse proxy like nginx. This would mean you don't have to redeploy or restart your application if the IP address changes. Please see this guide for details on how to configure nginx: https://docs.nginx.com/nginx/admin-guide/security-controls/controlling-access-proxied-tcp/
Otherwise I'd refer to this article: https://access.redhat.com/solutions/18412 describing the following configuration in WEB-INF/jboss-web.xml:
<valve>
<class-name>org.apache.catalina.valves.RemoteAddrValve</class-name>
<param>
<param-name>allow</param-name>
<param-value>127.0.0.1,127.0.0.2</param-value>
</param>
</valve>
</jboss-web>
To me this concern should be handled on infrastructure level, not in application container. I would suggest to look into AWS Security Groups or equivalent concepts in other cloud providers.
If you are running it in private cloud/bare metal, you should investigate to restrict it on transport layer your infrastructure provides. There should be some possibility to configure firewall rules.
I have created a Spring Boot microservice and hosted inside a Tomcat on a Linux machine.
Everything is inside the container and the container is inside the IBM cloud private platform.
Now the microservice should be running continuously.
But suppose for any reasons the microservice got stop or tomcat got crashed.
Is there any way we could restart the Tomcat server or microservice automatically without manual intervention?
Why are you deploying a Spring boot app in your local tomcat? By default Springboot comes with embedded Tomcat server in it, so if you just build and run the jar, a tomcat will be started with the service itself.You can also , configure the server type(tomcat or jetty) and other server properties in the application.yml file. More details here - https://www.springboottutorial.com/spring-boot-with-embedded-servers-tomcat-jetty
Coming to the second part, of the question,about how to make sure , that if one service crashes, a new instance should be started automatically, for this you might be needing to do some reading on container managers like dockerswarm or kubernetes, which support auto-scaling, and can take care of restarting services (pods) as and when required,they can even scale up, meaning increase the number of instances of a service if existing containers reach a resource usage threshold and then load balancing requests to that service through some discovery and registry client.I think this would be helpful to you - https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy
I'm complete able to configure spring boot in both cases, the question here is which of them are more robust and is the more recommended, because I didn't find in the spring boot documentation the recommended way to deploy it in a production environment, my concerns about use the embedded container are:
If I want to set it as a Windows or Linux service, is the jar file the best option?
If I use the jar file I'm not going to have access to restart the server.
Maybe in the future I need more applications in the same container.
If I restart the machine I have to execute again the java -jar.
The question in general is which is better use the jar file and execute it as java -jar jarname.jar in production or change the packaging to war set the tomcat as provided and set the generated war in an empty tomcat.
I hope you can help me.
---EDIT---
Many times the answer is depends, this is for a normal web application or REST web service.
jar packaging is perfectly suitable for production and you should rather fallback to war only if you really have to - which is often the case when you cannot control your deployment environment (which is often the case in large enterprises).
There is a chapter in Spring Boot Reference about setting up Spring Boot based application as a Unix/Linux/Windows service: Installing Spring Boot applications.
Regarding your concern:
Maybe in the future I need more applications in the same container.
With embedded containers if you need more applications running on the same machine, you should start two applications separately, each running on different port and effectively you will end up with two containers running - which is good, applications are better isolated from each other.
About a month ago I had the question like yours.
Let me share my conclusion:
1) JAR:
You can run independently every appliction with different ports (in linux, java -jar ... > app_logs.log &) and you can route it (e.g. nginx). Note that, restarting is not problem. You can write custom bash script (like this: ps aux | grep appname and kill by PID)
But there are some problems with configuring production app. Property files will archived into jar.
2) WAR
You can deploy into container and just run it. Easy managing at the server. If you want to re-configure app, open properties file from unarchived folder inside container, change it as need and restart container. So, managing and configuring will be easy.
But, if you want to run another app in this server with another port, then you must install another copy of container and config it.
So, in my practice, using war app easier than jar to manage and re-configure.
I don't know that much about Windows services but on Linux you can add the execution of a jar to a RC-Scripts (and thus make the application start at a certain run-level). For a spring boot app you just have to symlink to the jar and you can start/stop/etc like any other service, see: Spring Boot application as a Service
restart the machine or the JVM? A shutdown mechanism is built into spring boot, you just have to activate it (and you should enable security machanism so that not anybody can do that), see: How to shutdown a Spring Boot Application in a correct way?
Spring-Boot enables microservices - so the idea is to have one embedded webapp-container for each webapp/microservice. This reduces the risk of losing all services when only one is going down.
Yes. and you have to execute catalina.sh|bat start after every restart. Or you add an appropriate startup script (see 1.)
I sense that you'd rather do it the old-fashioned way. Despite the 'matter of taste' answer, there is one argument pro-jar: the only dependency is the JVM! The rest (the web-app-container, db-drivers, other libraries) is all part of the package you deliver. And if you decide to change the container for the next release, so will it be.
One more reason to use "war" file in production.
Springboot masked an error Jetty threw whereas WAR deployed in Jetty correctly caught it ( though issue below is still under review )
https://github.com/spring-projects/spring-boot/issues/8917#issuecomment-294673487
I don't know much about server kind of things, But my recommendation is
If you are using Monolithic application, better to use war with
external tomcat.
If you are using for Micro Service applications, use embedded
tomcat with different port. And each micro service applications are
independent from each other.
I am trying to figure out an easy way to manage many Spring Boot applications on my Production server. Right now I have many fat jars running on different folders where each one has its your own script to start/stop the application and there's an external folder for the configurations (logback, properties, xml). For record those configurations are loaded by command line -Dloader.path to Spring Boot execution.
So how can I avoid conflicts for the same http/https port already running on Production? Does exist any kind of application manager where system administrators could control it? One solution I found was to virtualize Spring Boot applications with Docker, but my environment is Unix Solaris.
Is there any java solution for this scenario?
You can have a look at Spring Cloud which will give you better control and management when running multiple boot applications. All components of Spring Cloud
might not be useful to you, but few of them will help in port resolution, service rerouting and property maintenance. Along with the above you can also try SBA.
Along with the above you can also try Nginx for UI load balancing and reverse proxy.
I have a standalone java application which uses java based TCP NIO to collect some information from various clients (not on web/HTTP but through some indigenously developed middleware). Now I have to develop a front-end for the users to perform a lot of querying through HTTP. So is there a way to put this application inside tomcat, so that servlets can invoke required functions on this application ???
The thing is it has to listen on that middleware outside tomcat too and at the same time service servlets inside tomcat. How to do this ??
Putting this application outside tomcat and using RMI is an option but I don’t want to do that.
Can embedding tomcat inside my application is an option ???
The brand-new Tomcat 7 has Embedded version for download.
Tomcat is big. You should try to embed Jetty, which is meant in order to make it possible.
http://jetty.codehaus.org/jetty/
I don't know about embedding Tomcat, but you can embed a servlet container inside your application using embedded Jetty. If what you want is to add an HTTP interface to an existing server, I think that's the way to go.
It also should be perfectly workable to launch your server's TCP listening components from a standard servlet in Tomcat. Then the servlet can call methods in your existing application directly, while it continues to listen to its usual TCP ports.
A third option is to write a servlet that just talks to your existing server in the same way other clients do.
The way you want to go, is to have an embedded web server to your existing application since you just need a little bit of web functionality.
Going the other way is possible. You can use servlet listeners to get started and stopped, and you need to take great care of any thread you start since Tomcat have no idea they exist.
As Traroth said, embedding Jetty is a much better option than doing the same with Tomcat. You have an example and a small tutorial in the Jetty website:
http://docs.codehaus.org/display/JETTY/Embedding+Jetty
You can always open the ports and listen manually if the requests aren't complicated.
Have you considered going the other way? That is embedding your application inside a web application?
Using spring you can instantiate your web application and then inject in into the appropriate web classes (e.g. struts2 actions).
This way you can deploy your web application into any web server that is preconfigured separate from your application.
If you do have to use Tomcat, you're best just making your application as a .war file which when Tomcat is ran will deploy your code. This can then talk to any RMI/middleware you like.
I'm not sure I understand your comment regarding memory spaces.
At a very basic level you have two choices:
Run your appication and the web
application in the same virtual
machine.
Run your application and
the web application in a different
virtual machine
If you take approach 1, you will be able to get instances of your applications classes from the servlets and call methods on them.
Embed tomcat / jetty inside your application. You will start your application normally through its main method. After starting your app you will need to create instances of the tomcat / jetty classes which will start up their own threads.
Embed your application inside a war file to be deployed on tomcat / jetty. Similar to the previous option instead you will need to start your application from a context listener.
If you prefer approach 2; start tomcat / jetty and deploy your web app and separately deploy your application. You'll now have two jvms running. To communicate between these two processes you'll have to use some form of socket communication: OutputStream/InputStream over sockets; RMI; JMX; JMS etc.