Spring boot get application base url outside of servlet context - java

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.

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;
}

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.

Related

Run java method to start database before Tomcat deploy

I am developing a web project with HSQLDB persistence. My database instance is on server mode, therefore, I need to run a cmd script/ Java method to access my schema.
Tomcat is the container I use to drop my war on port 8080. Gradle is my build system.
Currently I am using the following main method before I deploy my app to properly access my database on runtime:
public static void main(String[] args) throws IOException, ServerAcl.AclFormatException {
final String URL = "file:~/db/cursago";
String user = "user";
String password = "password";
HsqlProperties p = new HsqlProperties();
p.setProperty("server.database.0",URL+";user="+user+";password="+password);
p.setProperty("server.dbname.0","cursago");
Server server = new Server();
server.setProperties(p);
server.setLogWriter(null);
server.setErrWriter(null);
server.start();
System.out.println("Database is running with path: " + URL);
System.out.println("Username: " + user+", Password: " + password);
}
I would like to know if there's a way of making Tomcat/Gradle/IntelliJ IDEA run this main method before a project deploy, instead of running this script by hand.
from here:
you could run the content of your main in the onApplicationEvent like:
public class ApplicationListenerBean implements ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
final String URL = "file:~/db/cursago";
String user = "user";
String password = "password";
HsqlProperties p = new HsqlProperties();
p.setProperty("server.database.0",URL+";user="+user+";password="+password);
p.setProperty("server.dbname.0","cursago");
Server server = new Server();
server.setProperties(p);
server.setLogWriter(null);
server.setErrWriter(null);
server.start();
System.out.println("Database is running with path: " + URL);
System.out.println("Username: " + user+", Password: " + password);
}
}
This will trigger on every event, that could be application started or redeployed and happens before your application handles requests.
You also can wire in your properties.
There are some difficulties if the server is already running and it can't run in this scope only.

Error reading service account token from: [/var/run/secrets/kubernetes.io/serviceaccount/token]. Ignoring

when i run this code
public class test2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
String podName = "xrdpprocan";
String namespace = "default";
String master = "https://my_ip_adress";
Config config = new ConfigBuilder().withMasterUrl(master).withTrustCerts(true).build();
try (final KubernetesClient client = new DefaultKubernetesClient(config)) {
String log = client.pods().inNamespace(namespace).withName(podName).getLog(true);
System.out.println("Log of pod " + podName + " in " + namespace + " is:");
System.out.println("------------------");
System.out.println(log);
} catch (KubernetesClientException e) {
System.out.println(e.getMessage());
}
}
i get this Error reading service account token from: [/var/run/secrets/kubernetes.io/serviceaccount/token]. Ignoring.
Where is the problem: The current type of your client configuration is incomplete, you are missing the client authentication settings/data part.
Please be aware, when you are running your code from outside the cluster
(this type of client configuration is called out-of-cluster client configuration) you need to specify explicitly a bare minimum for successful connection to Kubernetes control-plane from outside.
Kubernetes Master URL
At least one method for user authentication, can be any of:
client certificates
bearer tokens
HTTP basic auth
You see the problem ? - you have specified none of these from the second condition for >> user << authentication (this is a key word here: user)
Right now Java Kubernetes client falls back into Service account based authentication strategy, thinking you are not human but robot (Pod running in context of Service Account).
Putting it technically, client is resolving now to the last resort option:
KUBERNETES_AUTH_TRYSERVICEACCOUNT
(4th on the list of fabric8io/kubernetes-client supported configuration option, check below)
which involves reading in service account token placed into the filesystem inside Pod's container at following path:
/var/run/secrets/kubernetes.io/serviceaccount/token
Officially fabric8io/kubernetes-client java client supports the following ways of configuring the client:
This will use settings from different sources in the following order
of priority:
System properties
Environment variables
Kube config file
Service account token & mounted CA certificate <== you client code tries this
System properties are preferred over environment variables. The
following system properties & environment variables can be used for
configuration
The easiest solution is to rely on Kube config file option to access cluster from outside, e.g.:
public class KubeConfigFileClientExample {
public static void main(String[] args) throws IOException, ApiException {
// file path to your KubeConfig
String kubeConfigPath = System.getenv("HOME") + "/.kube/config";
// loading the out-of-cluster config, a kubeconfig from file-system
ApiClient client =
ClientBuilder.kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath))).build();
// set the global default api-client to the in-cluster one from above
Configuration.setDefaultApiClient(client);
// the CoreV1Api loads default api-client from global configuration.
CoreV1Api api = new CoreV1Api();
// invokes the CoreV1Api client
V1PodList list =
api.listPodForAllNamespaces(null, null, null, null, null, null, null, null, null, null);
for (V1Pod item : list.getItems()) {
System.out.println(item.getMetadata().getName());
}
}
}
Full code sample can be found here.

Redirect all network of Android App (which is using Libraries) through a proxy network (if available)

I am working on an Android application and I am using various libraries like Picaso, Retrofit, Crashlytics, etc. and my college WIFI have proxy on it.
I know how to use a proxy when sending a HTTP requests to a server, but all the libraries that I am using have there own HTTP requests, so overriding all their HTTP classes would be a headache, and I am not even sure how to do that.
So, is there a way to route all the traffic of the App through a proxy (when available), like any library or some HTTP request overriding all the outgoing requests.
I implemented this as below.
(I forgot the original source).
import java.net.Proxy;
import java.net.ProxySelector;
//setting Application-Wide proxy Values
private void setProxy() {
//Device proxy settings
ProxySelector defaultProxySelector = ProxySelector.getDefault();
Proxy proxy = null;
List<Proxy> proxyList = defaultProxySelector.select(URI.create("http://www.google.in"));
if (proxyList.size() > 0) {
proxy = proxyList.get(0);
Log.d("proxy", String.valueOf(proxy));
try {
String proxyType = String.valueOf(proxy.type());
//setting HTTP Proxy
if (proxyType.equals("HTTP")) {
String proxyAddress = String.valueOf(proxy.address());
String[] proxyDetails = proxyAddress.split(":");
String proxyHost = proxyDetails[0];
String proxyPort = proxyDetails[1];
Log.d("proxy", proxyType + " " + proxyHost + " " + proxyPort);
System.setProperty("http.proxyHost", proxyHost);
System.setProperty("http.proxyPort", proxyPort);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Put this method in your base activity's onCreate method so it will get executed everytime user opens the application.
You can redirect specific network traffic (on a per application basis) as per the following link.
Network traffic via Proxy

Akka HTTP server with SSL support in Java - How to create configuration?

I am trying to create an Akka HTTP server, which will support SSL.
I am aware of this question for scala Akka HTTP 2.0 to use SSL (HTTPS) and I am trying to work it into Java code but I am getting lost.
The DSL akka.http.javadsl.Http class is different for Java and requires akka.actor.ExtendedActorSystem, when I try to create an instance for it I am required to create an application configuration with the com.typesafe.config.Config class, which I can't figure out how to instantiate and what to put in it.
Is there any simpler way? Or any classes I can use to create all the required configurations?
This is a snippet of the code:
// boot up server using the route as defined below
final ActorSystem system = ActorSystem.create();
final ActorMaterializer materializer = ActorMaterializer.create(system);
// Run the server bound to the local machine IP
String hostAddress = InetAddress.getLocalHost().getHostAddress();
// No implementation here?????
Config applicationConfig = new Config() {
}
ExtendedActorSystem extendedActorSystem = new ActorSystemImpl("HttpProxy", applicationConfig, ClassLoader.getSystemClassLoader(), Option.empty());
// todo: missing handler, settings, httpsContext and log
Flow<HttpRequest, HttpResponse, ?> handler;
ServerSettings settings;
akka.japi.Option<HttpsContext> httpsContext;
LoggingAdapter log;
new Http(extendedActorSystem).bindAndHandle(handler, hostAddress, PORT, settings, httpsContext, log, materializer);
System.out.println("Starting server on " + hostAddress + ":" + PORT);
// The server would stop if carriage return is entered in the system cosole
System.out.println("Type RETURN to exit");
System.in.read();
system.shutdown();
It supposed to be something like this:
// boot up server using the route as defined below
// Run the server bound to the local machine IP
String hostAddress = InetAddress.getLocalHost().getHostAddress();
// No implementation here?????
Config applicationConfig = ConfigFactory.load();
ActorSystem system = ActorSystem.create("HttpProxy", applicationConfig);
final ActorMaterializer materializer = ActorMaterializer.create(system);
// todo: missing handler, settings, httpsContext and log
Flow<HttpRequest, HttpResponse, ?> handler;
ServerSettings settings;
akka.japi.Option<HttpsContext> httpsContext;
LoggingAdapter log;
Http.get(system).bindAndHandle(handler, hostAddress, 9000, settings, httpsContext, log, materializer);
System.out.println("Starting server on " + hostAddress + ":" + 9000);

How to get the name or ip of a proxy server in a managed network?

i need to be able to access certain urls programmatically . I am using URLConnection as follows
URL url = new URL(http,
myProxy.com, // I need to know this parameter
-1,
http://www.example.com/);
How do I get the name of the proxy server used in a managed network.
when i use a browser like chrome it connects me with the proxy server that makes requests to the internet . How do i get the name of the proxy server ?
You can try to use a java ProxySelector class to do it, her is short example of it'usage from java proxy configuration guide:
private Proxy findProxy(URI uri)
{
try
{
ProxySelector selector = ProxySelector.getDefault();
List<Proxy> proxyList = selector.select(uri);
if (proxyList.size() > 1)
return proxyList.get(0);
}
catch (IllegalArgumentException e)
{
}
return Proxy.NO_PROXY;
}
To get a host name and IP address, you can use an InetSocketAddress, which you can get from Proxy instance:
InetSocketAddress addr = (InetSocketAddress) proxy.address();
if(addr != null) {
System.out.println("proxy hostname : " + addr.getHostName());
System.out.println("proxy port : " + addr.getPort());
}
But as I know, it's needed to set a system property to do it:
System.setProperty("java.net.useSystemProxies","true");
One more solution is to use a proxy-vole library to do it. Here is some usage examples.

Categories