Spring boot get application base url outside of servlet context
Solution 1
Suppose your app is using embedded tomcat server, then url to your app may be found as follows:
@Inject
private EmbeddedWebApplicationContext appContext;
public String getBaseUrl() throws UnknownHostException {
Connector connector = ((TomcatEmbeddedServletContainer) appContext.getEmbeddedServletContainer()).getTomcat().getConnector();
String scheme = connector.getScheme();
String ip = InetAddress.getLocalHost().getHostAddress();
int port = connector.getPort();
String contextPath = appContext.getServletContext().getContextPath();
return scheme + "://" + ip + ":" + port + contextPath;
}
Here is an example for embedded jetty server:
public String getBaseUrl() throws UnknownHostException {
ServerConnector connector = (ServerConnector) ((JettyEmbeddedServletContainer) appContext.getEmbeddedServletContainer()).getServer().getConnectors()[0];
String scheme = connector.getDefaultProtocol().toLowerCase().contains("ssl") ? "https" : "http";
String ip = InetAddress.getLocalHost().getHostAddress();
int port = connector.getLocalPort();
String contextPath = appContext.getServletContext().getContextPath();
return scheme + "://" + ip + ":" + port + contextPath;
}
Solution 2
In my setup I have a @Configuration class setting up the context path (hardcoded) and @Value injecting the port number from application.properties. The context path could also be extracted to a properties file and injected the same way, you would use:
@Value("${server.port}")
private String serverPort;
@Value("${server.contextPath}")
private String contextPath;
You can also implement ServletContextAware in your component in order to get a hook to the ServletContext which would also give you the context path.
I am guessing you would like to ship a complete url (including the full server name) in your emails, but you can't really be sure that the e-mail receivers are accessing your application server directly by hostname, i.e. it could be behind a web server, a proxy etc. You could of course add a server name which you know can be accessed from outside as a property as well.
Ben
Updated on July 09, 2022Comments
-
Ben almost 2 years
The setup is following - I have a timed task that would send verification emails so users:
@Scheduled(cron = " 0 0-59/1 * * * * ") public void sendVerificationEmails() { //... }
And in those emails I need to include a link leading back to the same webapp. However I can not find any references of how to get app's base url without servlet context.
BONUS
It would also help if I could set up thymeleaf template resolver here to work with those links, but for that I need a
WebContext
which requires an instance ofHttpServletRequest
. -
Ben over 7 yearsI'm not asking how to send emails or use thymeleaf templates, that's not relevant to the question and in fact, if you'd read the question carefully, you would realize that I already use thymeleaf templates and send emails. The real question is if the app is aware of it's base url, and how to get it - and your solution is to provide it myself, which does not help at all (and is a crude practice from deployment side). Besides @{} links in thymeleaf wont work if you dont make the the context HTTP-aware with
WebContext
-
eparvan over 7 yearsYou're right, I completely misunderstood your question, perhaps my edited answer you'll find more useful.
-
Ben over 7 yearsWill this work when deployed to a different web servlet container?
-
eparvan over 7 yearsI've tested only with tomcat and jetty, see my edited answer.
-
Ben over 7 yearsIt's messy because of deployment-dependency. Nevertheless I think this is a correct answer.
-
Karl.S over 6 yearsIn new versions of SpringBoot, it's
@Value("${server.context-path}")
, but's it's a good solution, thx.