Split spring boot app into multiple web apps - java

I want to split a large web app into different sections.
In my case there is a webshop, an api service, and then the main app.
and all of them should share a domain layer.
I'm trying to reproduce an ear layout without using a enterprise server, so the main app would be a war with a shared domain jar, and the admin app would have a contextPath /admin and also share the same domain.jar.
From start they would be deployed together but as the app grows I would simply start deploying the apps on there own ports and use nginx to glue them together.
I've implemented most of it in this demo github repo.
https://github.com/leon/springboot-multiproject
My question is:
How can I map the admin app to a sub directory of the main app?
/admin <- Admin app
/ <- Main app
and do I need to take any special considerations when it comes to the domain layer?
See https://github.com/leon/springboot-multiproject/blob/master/src/main/java/se/radley/main/Application.java#L23

I can't think of a particularly easy way to completely separate the parts of your application. One option might be to create two ApplicationContexts and spin-up two Tomcat servers, but then they will obviously need to run on different ports.
I would be tempted to keep things simple initially. You could create separate jars for your 'main' and 'admin' #Controllers, one for your domain and keep the application jar containing configuration. Component scanning will work withing nested jars so a single DispatcherServlet can happily server both the /admin and / controllers.
Either that, or perhaps just bite the bullet and break-up your applications from the start. At least that way you will be aware of any architectural issues early.

Related

How to deploy two .jar files on the same port?

I want to know how to deploy two different .jar files on the same port using Jenkins.
The two .jar files is build by Jenkins, i just want to know if there are any better options than re-doing the projects to build .war files and deploy them using a single Tomcat container?
edit:
The reason i'm asking the questions is because i'm building a webapp using multiple microservices, therefor i'm interested in how to do this with "best practice".
It sounds like what you want is a common point of access that your clients can use to access your services. You can achieve this by creating an API gateway service that routes requests to the correct service. Your original two services listen on different ports, but your client only has to know about the API gateway endpoints, the API gateway itself will route the requests.
Have a look at Spring-cloud-zuul or this tutorial to see how to do this.

How to deploy 2 microservices from 2 different jars into same port in spring boot

I'm new to Spring Boot.
I have deployed a microservice into port 80 in some server. This service has URL pattern root as '/test'.
Then I will have to deploy another microservice into same port in this same server. Its URL pattern is '/test2' from another different jar.
Is it possible to deploy 2 different jars that point to 2 different URLs into same port?
There’s two different ways to sort of do this:
1, The already mentioned way of using a proxy in front of the services, so users think they are running the same port, but really not. Nginx has a nifty proxy feature for this, and Netflix’s Eureka is 20% this too.
Build your two Spring applications as .war files, and deploy them to an application server like (non-embedded) Tomcat. There’s a good blog article on how to generate a .war and deploy it to a standalone Tomcat.
Put the two services in seperate Docker containers. (But you’ll still need to EXPOSE different ports to the outside world, so this answer is kind of cheating.
Option 2 is probably closest, and you’re still in Javaland... but it’s not the hip new way to deploy things in Spring Boot land in 2018.
Have a third microservice as proxy for the other two. Forward requests to them based on request content, context, URL pattern or anything suitable to your specific application.
If you have the code for both,
Dont need the code, just include the class names (by scanning the jars or asking the dev team)
Can make a new main method that scans all the packages and adds them to the context. Then start that method. I think it will scan all jars in class path. So even if your new main method is in one jar it will scan classes in the other jar. That way wont have to repack to one jar.
This is one way to keep one JVM and one port.
The proxy method suggested by Timir is fine too. Instead of a Java microservice I will suggest use Nginx or apache web server for composing, Run the two Java processes in a different system or different port if same system as the web server.

In tomcat deploy mulitple apps with some context but make them think as they are root app

I am not sure what I am asking is correct approach or not. So, let me first clarify my requirement.
Till date I was using each app as a root app and was deploying them in separate tomcat instance, but my app number are now growing and I can not keep on deploying a separate instance of tomcat for each app.
There are two things which make me deploy every app as root:
For updating an app you have to shutdown tomcat instance which will also stops other app running in same instance. And I do not want this to happen (as some users are live on one web app or some job is running on some app, so I can not stop all apps at any given time).
For writing urls, if I deploy a web app as root, then in web-app I can simply write "/students/list" , but if I deploy them in same instance with some different context name, then I have to write context name before the urls, like "ctxt1/students/list"
And for developers sake I don't want them to write context name before every url in web-app and also I don't want context names to appear to a user.
Is there any approach with which I can solve these 2 problems. I am thinking of migrating to Glassfish for some apps. If glassfish offer solution to these problems then I can migrate all apps to glassfish as well
Secondly I am running tomcat behind IIS, using ISAPI. If IIS can be of any help here?
You should not use one tomcat per App. The amount of tomcats should increase only when needed (really needed).
It is not true that you have to kill the whole tomcat, for one App update, you should only restart the specific context (going to http://your.tomcat:8080/manager/html).
About the URLs you can use an apache in front with mod_proxy_ajp configured to talk with tomcat (see this: http://httpd.apache.org/docs/2.2/mod/mod_proxy_ajp.html)

Nested apps within a WAR file in Geronimo

I am not an experienced web developer but lately I have been involved in the development of some web applications (Java Servlets + JavaScript + HTML5). With experience in standalone projects this question makes sense to me but I understand it can be absurd for an expert web developer:
I would like to develop some common applications and integrate them into bigger projects.
For example, I would like to develop an users manager web app which could be used by different products. So I could encapsulate it into a WAR file and include it in a project or another.
As it is explained here, I understand a WAR package is not a JAR containing libs but a package to deploy a complete application.
My goal is to reuse the same code without having to include all "UsersManager" files one by one into App1 and App2 packages. Currently, I think the best solution is to publish "UsersManager" and call it from App1 or App2. Nevertheless, if "UsersManager" and "App1", for example, are published at different contexts they don't share session variables. If "UsersManager" includes a Login service and it creates some session data these session variables should be accesible from "App1".
What should I try?
Make a redirect call from App1/App2 to UsersManager?
Forget about sharing sessions?
What is the right solution to this kind of problems?
Since Geronimo will use a Cookie to store the client session anyway (at least with my configuration),
all the web applications will require the client to accept Cookies.
On the other hand, at my company we have already a centralized session manager. I will use an additional cookie to store the session id provided by that system so that I have already a simple SSO mechanism.

Adding a web interface (Spring MVC) to existing Java application

I have an existing Java application (Spring based) that currently does NOT have a web interface, nor does it run in a web container. It packages up nicely with a start program and just works.
What I need to do is add an administrative web interface for some administrative type things, retrieving real time metrics, and perhaps some graphs to give the users a warm fuzzy feeling knowing that everything is working. As we are a Spring shop, and some of our web applications already use Spring MVC it only makes sense to us, however, I'm not happy with the suggestions I've had from our internal Spring folks on how I should procede.
What would be the ideal way to bolt on this web interface?
Convert my application to a web application and have a web container launch the application. I not too keen on this approach is the web tier is really secondary to the primary application.
Create a separate project that packages as a war, embed Jetty in my existing app and have it load the war. I think I can use the context loader listener to make the root context of my application the parent to the web application spring context. This would involve breaking up my Maven project into 2 projects I believe. I can't use an existing web technology for communication between the web tier and the primary application as my primary application is not web enabled.
Embed Jetty and put the Spring MVC stuff directly in my app. While I've done this approach before, it does involve some ugliness - for instance exploding the JSP tag libs into my jar.
Any thoughts on some clean separation here?
Also of note, my current jar contains some utility applications which some shell scripts launch. Going a pure WAR route would make this not so easy, since I can't juse point java at my war file and choose a class to execute.
Thanks.
If it's true that web is just a minor addition the application, migrating it to WAR and deploying in servlet container might be an overkill. Embedding web server/servlet container looks much simpler, although it doesn't have to be Jetty or Tomcat. You can use web server built into JDK or write one on top of netty or even raw sockets. But that's a hell to maintain.
Yet another solution to springs to mymind when reading:
web interface for some administrative type things, retrieving real time metrics, and perhaps some graphs
Maybe you don't need an interface, but monitoring infrastructure instead? Check out JMX (Spring has great support for JMX) - and write a second web application that simply connects to your standalone Java app via JMX and displays the metrics in fancy way. Another approach is to expose JMX via Jolokia, which translates JMX to REST services.
This approach has several advantages:
monitoring API is universal, and you get it for free
you don't have to use web client, monitoring application is completely decoupled,
finally changes to your original application are minimal. Check out this proof of concept: 1, 2.
It really depends on the structure of your existing Java/Spring app and how much of an API it provides. I've done something similar to this and I approached it by creating a separate Spring MVC project and then specified the existing Java app as a JAR dependency.
This is easy with Maven (or Ivy, etc) and provides nice decoupling. The trick is to be able to write service classes in the Spring MVC app which then access data via your dependent Spring app via a simple DAO class. That's why I stated at the beginning, that it depends on the structure of your original Java app. It has to be able to provide an API for data access that you can then plug your DAO (impl) into.
If this is not easily done, then the next option I'd suggest is simply converting your Spring app to a Spring MVC app. I've worked on another app where we did this. Using Maven, its possible to specify that the build can create either a war file or a jar file (or both). So it can be deployed as either a webapp (via war) or a normal app (via jar). Yes, the jar version has a bit of bloat but its a worthwhile compromise.
The question of embedding Jetty or using Tomcat via a war file is a completely separate issue that has its pros and cons. It shouldn't affect the approach you take in architecting the web app in the first place.

Categories