Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring boot get application base url outside of servlet context

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 of HttpServletRequest.

like image 645
Ben Avatar asked Nov 03 '16 12:11

Ben


2 Answers

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;
}
like image 189
eparvan Avatar answered Sep 22 '22 06:09

eparvan


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.

like image 36
Kristoffer Avatar answered Sep 23 '22 06:09

Kristoffer