I am trying to connect to AS400 using the TelnetClient from Apache in Java.
The goal for now is to simply connect and read the screen line by line and display each line. I will focus on input and interaction later.
When I connect via telnet, my program gets 'hung up' when it tries to read the input line. I think the thread is blocked by: line = bfIn.readLine() because this is where the application stops. It does not crash, it is just stuck there.
If I connect to a simple telnet switch using a different host and the same program, the program prints out the page just fine, so I am wondering if there is an extra step to connect to the AS400 specifically? Can you connect to AS400 through Apache TelnetClient for java? If not, how can you connect to AS400 through java and interact with the page (seeing what the page displays)?
Here is the code I have been working with:
import org.apache.commons.net.telnet.TelnetClient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.OutputStreamWriter;
public class AutomatedTelnetClient {
private TelnetClient telnet = new TelnetClient();
private InputStream in;
private PrintStream out;
private String prompt = "%";
public AutomatedTelnetClient(String server, String user, String password) {
try {
// Connect to the specified server
telnet.connect(host, 23);
in = telnet.getInputStream();
out = new PrintStream(telnet.getOutputStream());
BufferedReader bfIn = new BufferedReader(new InputStreamReader(in));
PrintWriter writer = new PrintWriter(telnet.getOutputStream(), true);
System.out.println("BufferedReader ready to be read: " + bfIn.ready());
try {
String line;
while ((line = bfIn.readLine()) != null) {
System.out.println(line);
}
}
catch (IOException e) {
System.out.println("Exception");
e.printStackTrace();
}
telnet.disconnect();
in.close();
bfIn.close();
An issue which I think might be occurring is the BufferedReader may not be able to pick up what AS400 returns to it upon connection so it cannot read it correctly.
Please note that the bufferedReader.ready() is returning false. I have made sure the host is valid and working using a command line connection.
Standard telnet can work with the IBM i, but it's not ideal since the 5250 protocol is designed for "screen at a time" "smart" terminals, not line or character at a time dumb terminals.
Are you aware of the TN5250J project?
tn5250j is a 5250 terminal emulator for the AS/400 written in Java.
Also for mobile access, something else to look at would be IBM i Mobile Access provided by IBM.
Related
I'm trying to connect to a remote machine which has docker installed. I want to exec into the docker container and connect to database and then fetch a table data using java.
Following are my commands that i'm trying to execute.
docker exec it containerID - to login to docker container
cqlsh -u username -p password -- to connect to cassandra DB
use keyspace; ---to connect to cassandra keyspace
desc tables; --- to view the tables that are available in keyspace.
Following is the Java code that I'm trying. Can someone let me know if this approach is correct or what should i do to make this code work. I'm completely new to java code.
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
public class ExecuteanyCommands {
public static void main(String[] args) throws JSchException, InterruptedException, IOException {
//JSch
JSch jsch = new JSch();
Session session = jsch.getSession("cambi", "10.10.96.20", 22);
session.setPassword("axone");
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
Channel channel = session.openChannel("exec");
InputStream in = channel.getInputStream();
((ChannelExec) channel).setCommand("docker exec -it containerID; cqlsh -u username -p password; use keyspace; desc tables;");
channel.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
while((line = reader.readLine()) != null) {
System.out.println(line);
}
channel.disconnect();
session.disconnect();
}
}
If you want to connect to a container from a remote machine over SSH, then the way to do it is to define an SSH tunnel, external to your Java program.
In addition, the idea of interacting with Cassandra by running cqlsh on the host is very unusual.
It's better to use the official Cassandra Java driver for that purpose.
To summarize:
Create an SSH tunnel between the client and the docker host
Write a Java program that uses the Java Driver to query Cassandra
I echo Jonathan Jacobson's point that your method isn't the correct. Running cqlsh which itself is an app/client to retrieve data from your Cassandra tables is incorrect.
You need to instead use one of the available Cassandra drivers to connect to your cluster. In your case, it would be the Java driver for Apache Cassandra.
On the Astra DB docs site, there's a fully working Java code example for connecting to a cluster. Here's a stripped down version that you can use:
import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.cql.ResultSet;
import com.datastax.oss.driver.api.core.cql.Row;
public class ConnectDatabase {
public static void main(String[] args) {
try (CqlSession session = CqlSession.builder()
.withAuthCredentials("your_username","your_password")
.build()) {
// select the release_version from the system.local table
ResultSet rs = session.execute("SELECT release_version FROM system.local");
Row row = rs.one();
// print the results to the console
if (row != null) {
System.out.println(row.getString("release_version"));
} else {
System.out.println("An error occurred.");
}
}
System.exit(0);
}
}
You'll need to get a copy of the example pom.xml file to compile the app. You can get more information about the Java driver here.
Note that you will need to expose the ports in Docker so that Cassandra is accessible from outside the container. For example, map the CQL port with -p 9042:9042.
If you're new to Cassandra, I recommend having a look at datastax.com/dev which has lots of free hands-on interactive learning resources. In particular, the Cassandra Fundamentals learning series lets you learn the basic concepts quickly.
For what it's worth, you can also use the Stargate.io data platform. It allows you to connect to a Cassandra cluster using APIs you're already familiar with. It is fully open-source so it's free to use. Here are links to the Stargate tutorials on datastax.com/dev: REST API, Document API, GraphQL API, and more recently gRPC API.
Finally, we also run live workshops for free to teach developers how to build apps for Cassandra. We provide all the materials including all the source code for fully working apps plus coding environments on the cloud so there's nothing for you to install. There are 2-3 workshops every week and details are at datastax.com/workshops. Cheers!
I have a need to create a http or https URL object from an IPv4 address (String or InetAddress objects - either one is ok) in Java. I have been at this for 10 hours now.
Attempts that hit a wall described below:
Attempt #1: I tried to make the URL by assembling a string, and then feeding it to a URL constructor.
Textbook states that a URL can be "protocol://host", with host being either a host name or IP address. but creating a URL like this: URL a = new URL("http://151.101.65.69"); and opening a stream to this URL (a) gives a HTTP error 500 (Internal Server Error - An unexpected condition occurred that the server does not know how to handle).
What get me fuming is that URL a = new URL("http://stackoverflow.com"); works.
At this point I am stuck. I have no Idea what to change, or how to move forward.
Attempt #2: I tried to do a reverse lookup on the IP address using "getHostName()" method in the InetAddress class.
this should return the host name by doing a reverse DNS lookup. Yet, I keep trying it for 151.101.65.69 (stackoverflow web server IP address), and the look up fails. By fails I mean the IP address is returned as string rather than the host name as a string. I read the Oracle docs http://docs.oracle.com/javase/1.5.0/docs/api/java/net/InetAddress.html#getHostName(), but I don't understand how to overcome the "security manager" the document mentions (or if it is indeed the reason the reverse lookup fails).
I also tried "getCannonicalHostName()", but that didn't fly either.
I am trying to figure out how to open a website using the IP address. It looks like my browser is running into the same issue as my code. I read up on How to access site through IP address when website is on a shared host? but I do not have any user names, as I want to be able to open any website that a user has an IP address for. Adding a port (such as 80) does not seem to work; neither does leaving the user name blank or using a generic 'user' or 'guest'.
I need is to create a URL object from an IPv4 String or InetAddress object, and I am stuck. I understand that a knowledgeable programmer such as you, may say that making URLs from IP addresses is not what IP addresses are for, or point out that I am not including a file portion of the URL, but that is not the problem at this moment. Could you please help me with my core challenge?
The answer provided by D.B. is good. I had very similar code; but you will find that this code will not work every time. There are IPv4 addresses you pass to the code offered D.B.'s answer which will not be able to open a URL stream (for example the IP address for stackoverflow). I thought the problem was my coding, and that is what I was hoping to get help with on stackoverflow. But I now realize the problem was my lack of understanding when asking this question. What I now understand, is that having an IPv4 address is not sufficient to open every website on the web. Anytime a server hosts multiple websites, the IP address can be used to connect to the server, but not to simultaneously identify the website we want to open/access. This gentleman explains this quite well: http://ask-leo.com/why_doesnt_accessing_a_site_by_its_ip_address_work.html
#D.B. thanks for taking the time to help. Much appreciated!
The following code works for me.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
public class InetAddressMain {
public static void main(String[] args) {
try {
InetAddress addr = InetAddress.getByName("172.217.4.110");
URL url = new URL("http://"+addr.getHostAddress());
InputStream is = url.openStream();
InputStreamReader isReader = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isReader);
String line;
while((line = reader.readLine()) != null){
System.out.println(line);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Output:
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="en"><head><meta content="Search the world's information, including webpages, images, videos and more. Google has many special features to help you find exactly what you're looking for." ... [output shortened for readability]
I'd really appreciate anyone with knowledge about how to communicate between applications to help me with my confusion. I've been spending a lot of time trying to figure this out.
I am currently working on an electronic gradebook that among other things allows the user to store students and grades in a Java desktop application. I want to be able to send that information (assignment names, student grades, etc.) over the Internet through a stream to a Ruby on Rails SQLite3 database. The purpose is so that students can access reports relating to their grades from the Ruby on Rails application. I’m hoping to make the connection as simple as possible. Both the Java and Rails applications are mostly complete (although Rails SQLite3 database needs to be normalized).
I'm thinking about using an HTTP POST request, such as the one I'm working on below, to send the information from Java to the Rails database. My question is as follows:
Since the web application CURRENTLY is not attached to a server but instead being run on a virtual machine is it possible to make an http request that, for demonstration/testing purposes, can connect from a Java to a Rails application that is on the same computer? The idea is that hopefully I could test and demonstrate with both the Java and Ruby on Rails running on my own computer then eventually use the same http request or a modification of it to connect to a server (when I eventually deploy the web-based application to the server). If that could be done then how would it be done. And, if it can't be done then what alternative exist.
import java.io.*;
import java.net.*;
public class HTTPPostRequestWithSocket {
public void sendRequest() {
try {
String params = URLEncoder.encode("param1", "UTF-8") + "="
+ URLEncoder.encode("value1", "UTF-8");
params += "&" + URLEncoder.encode("param2", "UTF-8") + "="
+ URLEncoder.encode("value2", "UTF-8");
String hostname = "nameofthewebsite.com";
int port = 80;
InetAddress addr = InetAddress.getByName(hostname);
Socket socket = new Socket(addr, port);
String path = "/nameofapp";
// Send headers
BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream(), "UTF8"));
wr.write("POST " + path + " HTTP/1.0rn");
wr.write("Content-Length: " + params.length() + "rn");
wr.write("Content-Type: application/x-www-form-urlencodedrn");
wr.write("rn");
// Send parameters
wr.write(params);
wr.flush();
// Get response
BufferedReader rd = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
System.out.println(line);
}
wr.close();
rd.close();
socket.close(); // Should this be closed at this point?
} catch (Exception e) {
e.printStackTrace();
}
}
}
Re " web application [...] run on a virtual machine is it possible to make an http request that, for demonstration/testing purposes, can connect from a Java to a Rails application that is on the same computer?"
With the network properly configured in the VM configuration the guest system looks like an ordinary host (with its own unique MAC and IP address) to any other host on the network. So yes, it is possible.
I have Gui Application written which running on windows,and i want to connect to remote unix machine and perform actions there such like API's ,go over the log file in the machines and send back to the application the last log file or others API that i want to perform on the remote machine.
In the remote machine i don;t have application server i just have Java which installed there.
I want to use Java in order to perform remote API over the remote machine;
what is the advice ,can i use web services ,can any one please advise.
Thanks in advance.
If Java can perform the actions you're talking about, I would use Sockets to communicate with the UNIX-Machine (over TCP/IP).
Your Windows-PC would be the client sending commands to the Unix-PC.
Web services would be a bit heavy handed option, esp if you opt for the SOAP ones. If you don't have a problem with the client and server always being Java, RMI seems to be the simplest solution to this problem since it's communication between two different JVM's using the normal method calling mechanism (with some additional interfaces and rules to be followed to please the RMI specification).
The Spring Framework ships with a number of remoting options that are all very easy to setup. You can use their classes for simpler configuration of something standard like RMI or JMS, or use a lightweight web services protocol such as Spring's HTTP invoker or Hessian.
For analyzing log files of remote machines you can always use Apache Commons sftp programmatically to FTP a copy of the remote log file to your PC.
If you configure the log files to be rotatable or to rotate each time they reach a specific size, you can avoid reloading the same information over and over.
You can use Ganymed SSH-2 for Java to ssh to the remote host from Client Java App and run the commands. No need to run any additional components on remote server. You can do password based authentication or key based authentication to login to remote host. We had successfully used it to administer (start/stop/grep log files, etc.) applications running on remote UNIX hosts. You can capture output of the remote command using the StreamGobbler class provided in the package. You can pass multiple commands separated by semi-colon in one remote call.
Basic Example included in the package:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
public class Basic
{
public static void main(String[] args)
{
String hostname = "127.0.0.1";
String username = "joe";
String password = "joespass";
try
{
/* Create a connection instance */
Connection conn = new Connection(hostname);
/* Now connect */
conn.connect();
/* Authenticate.
* If you get an IOException saying something like
* "Authentication method password not supported by the server at this stage."
* then please check the FAQ.
*/
boolean isAuthenticated = conn.authenticateWithPassword(username, password);
if (isAuthenticated == false)
throw new IOException("Authentication failed.");
/* Create a session */
Session sess = conn.openSession();
sess.execCommand("uname -a && date && uptime && who");
System.out.println("Here is some information about the remote host:");
/*
* This basic example does not handle stderr, which is sometimes dangerous
* (please read the FAQ).
*/
InputStream stdout = new StreamGobbler(sess.getStdout());
BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
while (true)
{
String line = br.readLine();
if (line == null)
break;
System.out.println(line);
}
/* Show exit status, if available (otherwise "null") */
System.out.println("ExitCode: " + sess.getExitStatus());
/* Close this session */
sess.close();
/* Close the connection */
conn.close();
}
catch (IOException e)
{
e.printStackTrace(System.err);
System.exit(2);
}
}
}
I use the library from apache.org and use the code from java2s.com:
import org.apache.commons.net.ftp.FTPClient;
import java.io.IOException;
import java.io.FileOutputStream;
public class Main {
public static void main(String[] args) {
FTPClient client = new FTPClient();
FileOutputStream fos = null;
client.connect("ftp.domain.com");
client.login("admin", "secret");
client.enterLocalPassiveMode();
String filename = "sitemap.xml";
fos = new FileOutputStream(filename);
client.retrieveFile("/" + filename, fos);
fos.close();
client.disconnect();
}
}
I downloaded the library, moved it to the lib folder and renamed it to cn.jar.
compiling: (under Windows 7)
javac -cp ".;lib\cn.jar" Main.java
running: (under Windows 7)
java -cp ".;lib\cn.jar" Main
and I've got: http://freelifer.narod.ru/some.png
How to fix it? What is wrong?
My guess: the FTP protocol defines two connections - a data connection and a control connection. Your sample code established the control connection successfully:
client.connect("ftp.domain.com");
client.login("admin", "secret");
The default constructor of FTPClient defines that the data connection should be established in active mode (meaning that the server will try to open a connection to your client when you request a file). I think that the data connection cannot be opened due to your firewall or some other network issue. The data connection is opened here:
client.retrieveFile("/" + filename, fos);
You may try passive mode or you may check your network settings again. Passive mode is entered by calling the enterLocalPassiveMode method of FTPClient. This method causes a PASV (or EPSV) command to be issued to the server. Example:
client.connect("ftp.domain.com");
client.login("admin", "secret");
client.enterLocalPassiveMode();
Cheers!