Reputation: 1571
Hi I have a database on server that need SSH connection before.
For that i follow instruction of this post To create a tunnel and port forwarding.
I didn't do the same but i implement this class (that i created directely without all dialogs..)
And then in my application.properties I have this line:
spring.datasource.url = jdbc:mysql://localhost:3307/my_database?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
But this work when manually I launch the first class, and after that i launch my spring boot app.
How can i do that automaticly before application starting this class be instanciate.
That is my PortFrowarding class:
package com.demo.demo;
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/**
* This program will demonstrate the port forwarding like option -L of
* ssh command; the given port on the local host will be forwarded to
* the given remote host and port on the remote side.
* $ CLASSPATH=.:../build javac PortForwardingL.java
* $ CLASSPATH=.:../build java PortForwardingL
* You will be asked username, hostname, port:host:hostport and passwd.
* If everything works fine, you will get the shell prompt.
* Try the port on localhost.
*
*/
import com.jcraft.jsch.*;
import java.awt.*;
import javax.swing.*;
public class PortForwardingLR{
public static void main(String[] arg){
int lport;
String rhost;
int rport;
try{
JSch jsch=new JSch();
String host=null;
if(arg.length>0){
host=arg[0];
}
else{
host="[email protected]";
}
String user=host.substring(0, host.indexOf('@'));
host=host.substring(host.indexOf('@')+1);
Session session=jsch.getSession(user, host, 22);
String foo="3307:8.8.8.8:3306";
lport=Integer.parseInt(foo.substring(0, foo.indexOf(':')));
foo=foo.substring(foo.indexOf(':')+1);
rhost=foo.substring(0, foo.indexOf(':'));
rport=Integer.parseInt(foo.substring(foo.indexOf(':')+1));
// username and password will be given via UserInfo interface.
UserInfo ui=new MyUserInfo();
session.setUserInfo(ui);
session.connect();
//Channel channel=session.openChannel("shell");
//channel.connect();
int assinged_port=session.setPortForwardingL(lport, rhost, rport);
System.out.println("localhost:"+assinged_port+" -> "+rhost+":"+rport);
}
catch(Exception e){
System.out.println(e);
}
}
public static class MyUserInfo implements UserInfo, UIKeyboardInteractive{
public String getPassword(){ return passwd; }
public boolean promptYesNo(String str){
// Object[] options={ "yes", "no" };
// int foo=JOptionPane.showOptionDialog(null,
// str,
// "Warning",
// JOptionPane.DEFAULT_OPTION,
// JOptionPane.WARNING_MESSAGE,
// null, options, options[0]);
// return foo==0;
return true;
}
String passwd;
// JTextField passwordField=(JTextField)new JPasswordField(20);
public String getPassphrase(){ return null; }
public boolean promptPassphrase(String message){ return true; }
public boolean promptPassword(String message){
// Object[] ob={passwordField};
// int result=
// JOptionPane.showConfirmDialog(null, ob, message,
// JOptionPane.OK_CANCEL_OPTION);
// if(result==JOptionPane.OK_OPTION){
passwd="ItsNotMyPwd";
return true;
// }
// else{ return false; }
}
public void showMessage(String message){
JOptionPane.showMessageDialog(null, message);
}
final GridBagConstraints gbc =
new GridBagConstraints(0,0,1,1,1,1,
GridBagConstraints.NORTHWEST,
GridBagConstraints.NONE,
new Insets(0,0,0,0),0,0);
private Container panel;
public String[] promptKeyboardInteractive(String destination,
String name,
String instruction,
String[] prompt,
boolean[] echo){
panel = new JPanel();
panel.setLayout(new GridBagLayout());
gbc.weightx = 1.0;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridx = 0;
panel.add(new JLabel(instruction), gbc);
gbc.gridy++;
gbc.gridwidth = GridBagConstraints.RELATIVE;
JTextField[] texts=new JTextField[prompt.length];
for(int i=0; i<prompt.length; i++){
gbc.fill = GridBagConstraints.NONE;
gbc.gridx = 0;
gbc.weightx = 1;
panel.add(new JLabel(prompt[i]),gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weighty = 1;
if(echo[i]){
texts[i]=new JTextField(20);
}
else{
texts[i]=new JPasswordField(20);
}
panel.add(texts[i], gbc);
gbc.gridy++;
}
if(JOptionPane.showConfirmDialog(null, panel,
destination+": "+name,
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE)
==JOptionPane.OK_OPTION){
String[] response=new String[prompt.length];
for(int i=0; i<prompt.length; i++){
response[i]=texts[i].getText();
}
return response;
}
else{
return null; // cancel
}
}
}
}
And i an trying to launch this method before Application is running like that and it s not working:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SymspringdemoApplication {
public static void main(String[] args) {
someMethodThatDoesForwarding();
SpringApplication.run(SymspringdemoApplication.class, args);
}
private static void someMethodThatDoesForwarding() {
PortForwardingLR.main(null);;
}
}
Thank.
Upvotes: 0
Views: 1971
Reputation: 4667
You have several options.
PortForwardingLR.main()
from your main method.PortForwardingLR
before your program. You can also use OpenSSH to do the port forwarding.PortForwardingLR.main()
call your main method.In my opition, it would be best if you reworked the code in PortForwardingLR
into two methods: one for opening a connection, and one for closing connection. The goal is to have something like this:
class MyDatabaseWorker {
public void run() {
// Do stuff here
}
public static void main(String[] args) {
PortForwardingLR forwarder = new PortForwardingLR(hostname, user, password);
forwarder.addPortForward(3306);
forwarder.connect();
MyDatabaseWorker worker = new MyDatabaseWorker();
worker.run();
forwarder.disconnect();
}
}
This way, you can reuse PortForwardingLR class for different projects, your DB class is minimally polluted, and you ensure that your DB class is never run without port forwarding.
Be careful, though, because if there is another process listening on port you are forwarding to, this scenario will fail.
Upvotes: 1
Reputation: 688
It would be easier to help/understand if you actually posted your own code, but nevertheless if you want to establish port forwarding before Spring starts it's own bootstrapping, simply execute the code before Spring starts creating beans (ultimately the DB-related beans).
E.g.:
...
/* Execute your custom port-forwarding here */
someMethodThatDoesForwarding();
/* SpringBoot code continues.. */
SpringApplication.run(DemoApplication.class, args);
...
Upvotes: 1