Connect to an oracle db in jdbc over an SSH tunnel - jdbc

Currently we have to tunnel over SSH to access our Oracle database. In order to do this we have to make sure than putty or an equivalent program/script is running on the server doing this tunelling before the application is deployed to Tomcat/Glassfish/etc.
Has anybody found a way to have java handle this tunneling transparently? Perhaps a jdbc driver than itself wraps another jdbc drive handling the tunnelling for you right in Java?

My solution was to use Jsch from JCraft http://www.jcraft.com/jsch/ to open a tunnel when my application server starts up. I close the tunnel when the application server shuts down. I do this via a servlet context listener.
int findUnusedPort() {
final int startingPort = 1025;
final int endingPort = 1200;
for (int port = 1025; port < 1200; port++) {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(port);
return port;
} catch (IOException e) {
System.out.println("Port " + port + "is currently in use, retrying port " + port + 1);
} finally {
// Clean up
if (serverSocket != null) try {
serverSocket.close();
} catch (IOException e) {
throw new RuntimeException("Unable to close socket on port" + port, e);
}
}
}
throw new RuntimeException("Unable to find open port between " + startingPort + " and " + endingPort);
}
private Session doSshTunnel(int tunnelPort) {
// SSH Tunnel
try {
final JSch jsch = new JSch();
sshSession = jsch.getSession("username", "sshhost", 22);
final Hashtable<String, String> config = new Hashtable<String, String>();
config.put("StrictHostKeyChecking", "no");
sshSession.setConfig(config);
sshSession.setPassword("password");
sshSession.connect();
int assigned_port = sshSession.setPortForwardingL(tunnelPort, remoteHost, remotePort);
return sshSession;
} catch (Exception e) {
throw new RuntimeException("Unable to open SSH tunnel", e);
}
}

I have used Apache MINA SSHD for a project a while back and I remember that there was support ofr opening tunnels.
You can check out http://mina.apache.org/sshd/ for more info.
Other options are discussed on this quesiton : SSH library for Java

Related

Oracle connection timeout inside a Azure Function that cancels at 5mins

I have the following lines of code inside a Java function:
try{
context.getLogger().info("Paso001");
Class.forName("oracle.jdbc.driver.OracleDriver");
context.getLogger().info("Paso002");
Connection conn = DriverManager.getConnection(
params.get().getConnection(), params.get().getUser(), params.get().getPassword());
if (conn != null) {
context.getLogger().info("Connected to the database!");
} else {
context.getLogger().log(Level.SEVERE, "No connection to the database!");
return request.createResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR).body("Error").build();
}
context.getLogger().info("Paso003");
PreparedStatement sentencia = conn.prepareStatement(params.get().getSentence());
int index = 0;
for (Param param : params.get().getParams()) {
index++;
if (param.getType().equals("String")) {
sentencia.setString(index, param.getValue());
} else {
sentencia.setInt(index, Integer.parseInt(param.getValue()));
}
}
ResultSet rs=sentencia.executeQuery();
JSONArray result = JsonHelper.recordList2Json(rs);
context.getLogger().info(result.toString());
return request.createResponseBuilder(HttpStatus.OK).body(result.toString()).build();
} catch(Exception e)
{
context.getLogger().info("Paso00-err");
context.getLogger().log(Level.SEVERE, e.toString());
}
Loging only shows "Paso001" and "Paso002" but connection fails at 300000 ms (5 minutes) because no "Paso00-err" is shown in the logs. I assume that Azure Function is reaching maximum time.
Azure Function is inside a VNET integration and DATABASE is inside another local NET behind an ExpressRoute.
I have assumed that Firewall is correct because opening socket to Host:Port inside the funcion seems ok:
InetAddress IPv4 = null;
try {
IPv4 = InetAddress.getByName(connect.get().getHost());
} catch (UnknownHostException e) {
result = e.toString();
e.printStackTrace();
return request.createResponseBuilder(HttpStatus.OK).body(result.toString()).build();
}
try {
Socket s = new Socket(IPv4, Integer.parseInt(connect.get().getPort()));
result = "Server is listening on port " + connect.get().getPort()+ " of " + connect.get().getHost();
context.getLogger().info(result);
s.close();
}
catch (IOException ex) {
// The remote host is not listening on this port
result = "Server is not listening on port " + connect.get().getPort()+ " of " + connect.get().getHost();
context.getLogger().info(result);
}
Result gets: "Server is listening on port port of host host
Note. I get same error pointing to a public database installed locally.
Is there anything else missing to open? Any ideas?
Edit: I have rewritten code with .NET CORE 3.11...
using (OracleCommand cmd = con.CreateCommand())
{
try
{
log.LogInformation("step001");
con.Open();
log.LogInformation("step002");
cmd.BindByName = true;
cmd.CommandText = sentence;
OracleDataReader reader = cmd.ExecuteReader();
log.LogInformation("step003");
return new OkObjectResult(reader2Json(reader));
}
catch (Exception ex)
{
return new OkObjectResult("Error: "+ex.ToString());
}
}
and similar results but this time exception is going thrown:
Error: Oracle.ManagedDataAccess.Client.OracleException (0x80004005): Connection request timed out
at OracleInternal.ConnectionPool.PoolManager`3.Get(ConnectionString csWithDiffOrNewPwd, Boolean bGetForApp, OracleConnection connRefForCriteria, String affinityInstanceName, Boolean bForceMatch)
at OracleInternal.ConnectionPool.OraclePoolManager.Get(ConnectionString csWithNewPassword, Boolean bGetForApp, OracleConnection connRefForCriteria, String affinityInstanceName, Boolean bForceMatch)
at OracleInternal.ConnectionPool.OracleConnectionDispenser`3.Get(ConnectionString cs, PM conPM, ConnectionString pmCS, SecureString securedPassword, SecureString securedProxyPassword, OracleConnection connRefForCriteria)
at Oracle.ManagedDataAccess.Client.OracleConnection.Open()
at Oracli2.Function1.Run(HttpRequest req, ILogger log) in C:\proy\vscode\dot2\Oracli2\Oracli2\Function1.cs:line 50
You can increase the function time out in the hosts.json file, just so you are aware of that, but I dont think increasing it will fix your issue, 5 minutes is a generous time, unless the query you are running here does in-fact take longer than 5 minutes to return!
Can you set the retry_count & retry_delay for your connection string something small (eg: 3 tries) so you know that the time out is not because of trying to do 100 retries and not see the actual underlying error
Other issues could be to do with connectivity, best bet would be to go into the Kudu Console for the console app, open up SSH and via SSH see if you can connect to your oracle db and run a test query from here, if it's all working from here then connectivity is not the issue.

Programmatically capture the current screen shot in LG WebOS TV

I am trying to the screenshot of the LG TV. Running nmap gives me the following output.
Discovered open port 18181/tcp on xx.xx.xx.xxx
Increased max_successful_tryno for xx.xx.xx.xxx to 1 (packet drop)
Discovered open port 9998/tcp on xx.xx.xx.xxx
Discovered open port 9955/tcp on xx.xx.xx.xxx
Discovered open port 1998/tcp on xx.xx.xx.xxx
Discovered open port 3001/tcp on xx.xx.xx.xxx
Discovered open port 1267/tcp on xx.xx.xx.xxx
Discovered open port 1512/tcp on xx.xx.xx.xxx
Discovered open port 3000/tcp on xx.xx.xx.xxx
Discovered open port 1812/tcp on xx.xx.xx.xxx
Discovered open port 1552/tcp on xx.xx.xx.xxx
Discovered open port 36866/tcp on xx.xx.xx.xxx
Now, How i can get the screen shot of the current program running in the TV.
Thank you
Wondering How, i can get the screenshot of the TV ?
This code is used to turnOff the TV sending message via WebSocket
public static void turnOff(WebSocketClient ws) throws JSONException
{
JSONObject headers = new JSONObject();
JSONObject payload = new JSONObject();
try {
headers.put("type", "request");
headers.put("id", 10001);
headers.put("uri", "ssap://system/turnOff");
} catch (JSONException e) {
}
headers.put("payload", payload);
ws.send(headers.toString());
System.out.println(headers.toString());
}
This is the code that connects to the WebSocket in the TV
ws = new WebSocketClient(URI.create("ws://10.10.10.111:3000")) {
#Override
public void onOpen(ServerHandshake arg0) {
System.out.println("Connected ws://10.10.10.111:9000");
try {
// sendPin(ws);
register(ws);
} catch (JSONException ex) {
Logger.getLogger(LGWebTVClient.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
public void onMessage(String arg0) {
try {
System.out.println(arg0);
JSONObject message = new JSONObject();
try {
message = new JSONObject(arg0);
} catch (JSONException ex) {
Logger.getLogger(LGWebTVClient.class.getName()).log(Level.SEVERE, null, ex);
}
String type = message.optString("type");
try
{
String pin ="";
for (int i = 0; i < 9; i++)
{
if(type.equals("response"))
{
String id = message.optString("id");
if(id.equals("152463"))
{
Scanner scanner = new Scanner(new InputStreamReader(System.in));
System.out.println("Enter the PIN: ");
int number = scanner.nextInt();
System.out.println("Integer input: " + number);
pin = number+"";
if(number < 10)
pin ="00"+pin;
if(number < 99 && number > 9)
pin ="0"+pin;
if(i > 99)
pin =""+pin;
System.out.println("Sending PIN");
sendPin(ws,pin);
break;
}
}
}
}
catch (JSONException ex)
{
}
if(type.equals("registered"))
{
System.out.println("Registerd");
secondScreen(ws);
}
You could convert the HTML content into a canvas, then save it as a file.
However, this only renders HTML and CSS directly. It cannot capture anything outside of that.
Or, it might be possible to use getUserMedia() to take a screenshot of everything, and save that as a file.

How to connect to the MQ Server QUEUE MANAGER using MQ Client

I was try to send message to the MQ Server using the MQ Client
The error is:- A WebSphere MQ Error occurred : Completion Code 2 Reason Code 2058.I know this reason code because of the wrong Queue Manager Name..But the Queue Manager Name is correct...
After installed the WebSphere MQ Client I just run the command:
SET MQSERVER=QM_ORANGE/TCP/IPADDRESS(PORT NUMBER)
and run this program
public class MQSample {
// code identifier
static final String sccsid = "#(#) MQMBID sn=p750-002-131001_DE su=_FswqMCqGEeOZ3ui-rZDONA pn=MQJavaSamples/wmqjava/MQSample.java";
// define the name of the QueueManager
private static final String qManager = "QM_ORANGE";
// and define the name of the Queue
private static final String qName = "Q1";
/**
* Main entry point
*
* #param args - command line arguments (ignored)
*/
public static void main(String args[]) {
try {
// Create a connection to the QueueManager
System.out.println("Connecting to queue manager: " + qManager);
MQQueueManager qMgr = new MQQueueManager(qManager);
// Set up the options on the queue we wish to open
//int openOptions = MQConstants.MQOO_INPUT_AS_Q_DEF | MQConstants.MQOO_OUTPUT;
int openOptions = MQConstants.MQOO_OUTPUT;
// int openOptions1 = MQConstants.MQOO_INPUT_AS_Q_DEF;
// Now specify the queue that we wish to open and the open options
System.out.println("Accessing queue: " + qName);
MQQueue queue = qMgr.accessQueue(qName, openOptions);
//MQQueue queue1 = qMgr.accessQueue(qName, openOptions1);
// Define a simple WebSphere MQ Message ...
MQMessage msg = new MQMessage();
// ... and write some text in UTF8 format
msg.writeUTF("Hello, World!");
// Specify the default put message options
MQPutMessageOptions pmo = new MQPutMessageOptions();
// Put the message to the queue
System.out.println("Sending a message...");
queue.put(msg, pmo);
//
openOptions = MQC.MQOO_INQUIRE + MQC.MQOO_FAIL_IF_QUIESCING
+ MQC.MQOO_INPUT_SHARED;
queue = qMgr.accessQueue("QM_APPLE", openOptions,
null, // default q manager
null, // no dynamic q name
null); // no alternate user id
System.out.println("MQRead v1.0 connected.\n");
int depth = queue.getCurrentDepth();
System.out.println("Current depth: " + depth + "\n");
if (depth == 0) {
return;
}
MQGetMessageOptions getOptions = new MQGetMessageOptions();
getOptions.options = MQC.MQGMO_NO_WAIT + MQC.MQGMO_FAIL_IF_QUIESCING
+ MQC.MQGMO_CONVERT;
while (true) {
MQMessage message = new MQMessage();
try {
queue.get(message, getOptions);
byte[] b = new byte[message.getMessageLength()];
message.readFully(b);
System.out.println(new String(b));
message.clearMessage();
} catch (IOException e) {
System.out.println("IOException during GET: " + e.getMessage());
break;
} catch (MQException e) {
if (e.completionCode == 2
&& e.reasonCode == MQException.MQRC_NO_MSG_AVAILABLE) {
if (depth > 0) {
System.out.println("All messages read.");
}
} else {
System.out.println("GET Exception: " + e);
}
break;
}
}
queue.close();
//_queueManager.disconnect();
// Disconnect from the QueueManager
System.out.println("Disconnecting from the Queue Manager");
qMgr.disconnect();
System.out.println("Done!");
}
catch (MQException ex) {
System.out.println("A WebSphere MQ Error occured : Completion Code " + ex.completionCode
+ " Reason Code " + ex.reasonCode);
ex.printStackTrace();
for (Throwable t = ex.getCause(); t != null; t = t.getCause()) {
System.out.println("... Caused by ");
t.printStackTrace();
}
}
catch (java.io.IOException ex) {
System.out.println("An IOException occured whilst writing to the message buffer: " + ex);
}
return;
}
}
You have set the MQSERVER environment variable. MQ C Client understands this environment variable and accordingly connects to queue manager running on the machine specified in IP address. MQ Java does not behave in the same way.
In your application you have specified just the queue manager name in MQQueueManager constructor. This mean application wants to connect to queue manager running on the same machine via server bindings connection.
You could do as below to connect to queue manager: (change the host, port, channel and queue manager name). Note the sample is written with MQ v8 Java client.
Hashtable properties = new Hashtable<String, Object>();
properties.put(MQConstants.HOST_NAME_PROPERTY, "qm.mycomp.com");
properties.put(MQConstants.PORT_PROPERTY, 1414);
properties.put(MQConstants.CHANNEL_PROPERTY, "APP.SVRCONN");
properties.put(MQConstants.USE_MQCSP_AUTHENTICATION_PROPERTY,"true");
properties.put(MQConstants.USER_ID_PROPERTY, "myuserid");
properties.put(MQConstants.PASSWORD_PROPERTY, "passw0rd");
/**
* Connect to a queue manager
*/
MQQueueManager queueManager = new MQQueueManager("QM", properties);
Update
So you don't want to hard code connection parameters in your program? You can use the MQSERVER environment variable it self, get it, parse it and the connection parameters. You can also use a configuration file or a LDAP server to pull the connection information.
Update II
You have not read the MQ documentation at all. MQ Client is a set of libraries/jars/.net assemblies etc which expose APIs in different languages. You develop application using these APIs to communicate with queue manager. That is what you have done in your program above. Without these libraries you can't connect to a queue manager (many people think queue manager as server). When your application runs on the same machine as the queue manager, it is possible to communicate with queue manager over shared memory. But when running on different machine the communication is over TCP/IP (or SNA).
Hope this clears the confusion.

How to Keep Alive SNMP agent

I succcesfully created SNMP agent using snmp4j libraray
Here is the refrence code.
My query is how can i make this agent to run always to listen all incoming OIDs from manager.??
public synchronized void listen() throws IOException
{
TransportIpAddress address2= new UdpAddress(2069);
AbstractTransportMapping transport;
if (address2 instanceof TcpAddress)
{
transport = new DefaultTcpTransportMapping((TcpAddress) address2);
}
else
{
// transport = new DefaultUdpTransportMapping( (UdpAddress) address2);
transport = new DefaultUdpTransportMapping();
}
ThreadPool threadPool = ThreadPool.create("DispatcherPool", 10);
MessageDispatcher mtDispatcher = new MultiThreadedMessageDispatcher(threadPool, new MessageDispatcherImpl());
// add message processing models
mtDispatcher.addMessageProcessingModel(new MPv1());
mtDispatcher.addMessageProcessingModel(new MPv2c());
// add all security protocols
SecurityProtocols.getInstance().addDefaultProtocols();
SecurityProtocols.getInstance().addPrivacyProtocol(new Priv3DES());
//Create Target
CommunityTarget target = new CommunityTarget();
target.setCommunity( new OctetString("password"));
Snmp snmp = new Snmp(mtDispatcher, transport);
snmp.addCommandResponder(this);
transport.listen();
System.out.println("Listening on " + address);
try
{
this.wait();
}
catch (InterruptedException ex)
{
Thread.currentThread().interrupt();
}
}

Windows Phone 7 client server implementation

I'm trying to create an application for windows phone 7 which acts as a client and which sends requests to a server which is written in Java. The client supposed to send a request, and wait for an answer from the server.
My problem is that I can't seem to communicate with the server properly. When I tried testing it in a simple .NET C# program and used blocking calls such as socket.send() and socket.receive() it works but the Windows Phone application doesn't have blocking calls.
This is what the server (Java) does once it detects a connection:
BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), "UTF-8"));
String message = reader.readLine();
PrintWriter writer = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream(), "UTF-8"));
writer.println("hiBack");
writer.close();
and this is how the client(C#) is implemented:
public void sendRequest()
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
var connectionOperation = new SocketAsyncEventArgs { RemoteEndPoint = new DnsEndPoint(server, serverPort) };
connectionOperation.Completed += new EventHandler<SocketAsyncEventArgs>(onConnectCompleted);
socket.ConnectAsync(connectionOperation);
}
private void onConnectCompleted(object sender, SocketAsyncEventArgs e)
{
if (e.SocketError != SocketError.Success)
{
System.Console.WriteLine("Error! " + e.SocketError);
return;
}
var sendListener = new SocketAsyncEventArgs();
string msg = "hi";
var buffer = new System.Text.UTF8Encoding().GetBytes(msg + Environment.NewLine);
sendListener.SetBuffer(buffer, 0, buffer.Length);
sendListener = new SocketAsyncEventArgs { RemoteEndPoint = new DnsEndPoint(server, serverPort) };
sendListener.Completed += new EventHandler<SocketAsyncEventArgs>(onSendCompleted);
socket.SendToAsync(sendListener);
}
private void onSendCompleted(object sender, SocketAsyncEventArgs e)
{
socket.ReceiveAsync(e);
}
I've got a problem with the line: socket.SendToAsync(sendListener); on the C# side which end the program without doing anything (exit with return code 0).
the Java server starts it's work instantly when it detects the connection so it might also cause a problem?
What can I do to make the communication work?

Resources