i need to send some messages from my java web application to some servers using Diameter protocol, in particular CCR-CCA scenario. I had a look at jdiameter opensource project, but my usecase does not require such complexity, since that i just need to send a single request and log the response (actually i don't even need the CER-CEA part).
So i thought i could just have used Seagull running under my webapp. I downloaded Seagull (for Windows), and what i'm trying to do is basically to run the .bat file coming from Seagull for the diameter environment from my java environment.
That's what i've done till now..
1) A simple test to invoke the client.. Here wrapper simply sets working dir and starts the process
public static void main(String[] args) {
List<String> cmd=new ArrayList<>();
cmd.add("cmd.exe");
cmd.add("/c");
cmd.add("my_start_client.bat");
JavaProcessBuilderWrapper wrapper = new JavaProcessBuilderWrapper();
Process p = wrapper.createProcess(RedirectErrorsTo.STDERR,
new HashMap<>(), new File("my_working_dir"), cmd);
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
StringBuilder output = new StringBuilder();
String line;
try {
while ((line = reader.readLine()) != null) {
output.append(line);
}
System.out.println(line);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
2) I modified the client's and server's .bat files coming from Seagull to use CCR-CCA protocol.
Running Java main with this configuration caused a
Fatal: Keyboard saved configuration failure error
on my logs.
3) So, as mentioned here i further modified my client's .bat file to run in background mode, adding -bg at the end. Now my client's bat look like this
#ECHO OFF
rem
"Diameter Start Script Sample"
"Local env"
SET RUN_DIR=C:\Program Files\Seagull
set PATH=%PATH%;%RUN_DIR%
set LD_LIBRARY_PATH=%RUN_DIR%
set RUN_DIR=%RUN_DIR%\diameter-env\run
cd %RUN_DIR%
cls
mode 81,25
echo "Seagull Diameter Client Sample Start"
seagull -conf ..\config\conf.client.xml -dico ..\config\base_ro_3gpp.xml -scen ..\scenario\ccr-cca.ro.client.xml -log ..\logs\ccr-cca.client.log -llevel ETM -bg
pause
Since i was facing some troubles, to keep things simple, i just tried to make it work at least via cmd (not using my java method), but i think background mode is messing around, because now when i start my server and then my client in bg mode, sometimes i get a
Fatal: Forking error
but the most of the times, the client send a single message and then on my console i see that my software is causing connection abort (error code -1), and from the log i see that the channel just get closed, and my client does not even receive an answer. (NB for now i left the configuration files untouched)
Has any of you faced this behaviour? Is something else closing the connection (firewall perhaps)? Do i have to provide other configurations to make this work?
Once i can get this working, can i use my java web app (with a method similar to the one i already mentioned) to make diameter calls?
Thanks in advance, any help is really welcomed.
Related
Background
I am trying to create a java application to send ZPL command to a ZPL printer and get a label printed.
I set up a ZPL emulator(https://chrome.google.com/webstore/detail/zpl-printer/phoidlklenidapnijkabnfdgmadlcmjo) by following this post : Emulate ZPL printer
Issue
After setting the emulator up and add it as zpl printer via mac Printer&Scanner ,
I try to use lp command to print it. it is stable the reliable:
lp -o "raw" -q1 -d zpl <<< "^XA\n^FO50,60^A0,40^FDWorld Best Griddle^FS\n^FO60,120^BY3^BCN,60,,,,A^FD1234ABC^FS\n^FO25,25^GB380,200,2^FS\n^XZ"
However, my use case is send the command to a printer remotely on the network, Therefore I need to create a java application to send the Zpl command to the printer. It succeeds initially, then it randomly get splitted:
java code:
import java.io.*;
import java.net.*;
class TCPClient
{
public static void main (String argv[]) throws Exception
{
Socket clientSocket=new Socket("127.0.0.1",9100);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream() );
try {
outToServer.writeBytes("^XA\n^FO50,60^A0,40^FDWorld Best Griddle^FS\n^FO60,120^BY3^BCN,60,,,,A^FD1234ABC^FS\n^FO25,25^GB380,200,2^FS\n^XZ");
} catch (Throwable e) {
System.out.println(e);
}
outToServer.flush();
outToServer.close();
clientSocket.close();
// outToServer.flush();
}
}
Result:
So quite often, it succeeds once and then following 2 or 3 printing get fragmented or failed. I suspect it might be the socket TCP fragmentation issue. or there any socket option I can configure? But not sure how to solve it. Can anyone help here?
Update:
I try to use wireshark. The issue resides in the TCP package size:
For lp command, everything is sent as one single pack:
As for java app, it is broken down into smaller packs for some reason.
But I still don't know how to configure the pack size. Also it confuses me a lot why Java app will break the data packet to like 1 byte or two byte sized?
I think you are using a wrong method to send printing job. I'm not sure lp command uses Socket connection. Try calling lp from Java using Runtime.getRuntime().exec:
String cmd = "lp -o \"raw\" -q1 -d zpl <<< \"^XA\n^FO50,60^A0,40^FDWorld Best Griddle^FS\n^FO60,120^BY3^BCN,60,,,,A^FD1234ABC^FS\n^FO25,25^GB380,200,2^FS\n^XZ\"";
Runtime.getRuntime().exec(String.format(cmd));
I'm trying to read data from the server with SSH protocol. For this, I'm using the j2ssh library. My server connects with the other server in ssh without any problem. The problem is when I try to read any data from the shell command line. Whatever "command" I send to program "read = in.read(buffer)" never get any data, I tried with "ls" with "cat filename.txt" and other commands.
Only one command works fine and is "tail -f filename.txt". With this command, I can see the buffer is not empty, this contain the text of file, but the tail command does not close and while listening, sends the program in loop.
Can Anyone help me to know why I can't get any data from othere command?
This is my code:
private String exec(String cmd) throws SSHHandlerException {
String result = null;
session = ssh.openSessionChannel();
if(session.startShell())
{
session.getOutputStream().write((cmd+"\n").getBytes());
session.getOutputStream().close();
result = read(session,log);
}
session.close();
ssh.disconnect();
return result;
}
private static String read(SessionChannelClient session, ProcessLogger log) throws Exception{
byte buffer[] = new byte[255];
int read;
StringBuffer out=new StringBuffer();
InputStream in = session.getInputStream();
while((read = in.read(buffer)) > 0) {
out.append(new String(buffer, 0, read));
}
return out.toString();
}
If your goal is to transfer files, you should be using an SFTP client instead. SFTP is exactly what you're looking for: a file transfer protocol on top of SSH. It's much, much more efficient than using some command on the host and redirecting the stream.
J2SSH has an SftpClient implementation that can be constructed with an SshClient. Just use one of the get methods. Javadocs are here.
Edit after learning that you're not trying to transfer files:
You need to request a pseudo-terminal before you start the shell. From the docs:
The remote process may require a pseudo terminal. Call this method before executing a command or starting a shell.
Also, because it appears that you're using a Linux environment, I would recommend using terminal type "xterm" rather than their example of "vt100".
The reason that tail was working and not the other commands was because you were calling tail interactively. The interactive command creates its own pseudo-terminal of sorts. If, instead, you call tail -n 16 filename.txt then you will get the same results as with the other commands because it won't be interactive.
I have a simple Java application, basically a server implemented using com.sun.net.HttpServer API, that reads a file and simply sends back the texts after some processing. The server part simply looks like this:
server = HttpServer.create(new InetSocketAddress(serverPort), 0);
logger.info("EventRetriever REST server listening to port: " + serverPort);
server.createContext("/getEvents", new MedatadaHandler());
server.setExecutor(null);
server.start();
// ...
#Override
public void handle(HttpExchange he) throws IOException {
//...
String response = requestEvents();
he.sendResponseHeaders(200, response.length());
OutputStream os = he.getResponseBody();
os.write(response.toString().getBytes());
os.close();
}
//...
public String requestEvents(){
//...
// this printing on the console looks fine though:
logger.info(jsonString);
return jsonString;
}
I run my jar file with java -jar myApp.jar on a command line or simply on my IDE. I'm witnessing some weird behaviors, sometimes just hanging, when it requires sending texts containing special characters, such as the music symbol ♪. When I call the IP:PORT/getEvent via a browser, the behavior is so weird:
If I run it on a Windows Powershell or Command Prompt, the symbol appears as ? on the console, and what I get from the browser is also shown as ?. But when I run the program on a linux server or my Eclipse IDE, it is shown correctly on the console (as ♪), but on the browser, I get the following error, although the status is 200 OK. I see on the console the java application keep looping printing the line every few seconds (as if it is trying to send the data, but can't maybe something is blocking it!). But I don't get any exception or errors on the app (I log all possible errors).
I'm very confused for this behavior. What's going on?!
First, why what I get is dependent on the environment I run my Java app?! If Windows Command Prompt/Powershell shows the character as ?, I expect it just showing it locally like that. Why should I see it also as ? on my browser?! Java app must be independent of the environment.
And second, what is going on with that error on the Linux/Eclipse envrionment when requesting a line that has this character?
The issue as could be predicted, was related to getBytes() and UTF-8 String representations. Did the following and it was all good then:
he.sendResponseHeaders(200, response.getBytes("UTF-8").length);
OutputStream os = he.getResponseBody();
os.write(response.getBytes("UTF-8"));
I have set up a local proxy server for request logging but my java code ignores it and connects directly (Windows XP, JDK 1.7). Web browsers work with it. So I wrote test code for discussion that seems to connect directly even if a (bogus) proxy is specified. With the bogus proxy, I would expect connection failure but the code succeeds, connecting directly:
System.setProperty("http.proxyHost", "localhost");
System.setProperty("http.proxyPort", "12345");
System.setProperty("http.nonProxyHosts", "noNonProxyHost.com");
URL url = new URL("http://docs.oracle.com/javase/7/docs/technotes/guides/net/proxies.html");
InputStream in = url.openStream();
System.out.println("Connection via bogus proxy succeeded");
The code is run as standalone Java, no Maven, no applet, no container. I have a direct internet connection.
In your case using java.net.URL(), if the proxy server cannot be reached at http.proxyHost and http.proxyPort then it simply falls back and tries to do a direct connect. If that succeeds, you'll see no exception thrown which is why your code works without error. You should see a pause while it tries to find the proxy though.
This sample code below happily fetches the URL and displays it, without error, even when run with bogus proxy settings. -Dhttp.proxyHost=bogus -Dhttp.proxyPort=2345 but will talk to my local proxy localhost port 8888 if set correctly
import java.io.*;
import java.net.URL;
import java.util.*;
public class URLClient {
private static String sUrl = "http://www.apache.org/";
public static void main(String[] args) {
try {
URL url = new URL(sUrl);
InputStream is = url.openStream();
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
String output = s.hasNext() ? s.next() : "";
System.out.println(output);
} catch(Throwable e) {
System.err.println("exception");
}
}
}
The problem I was originally having with http.proxyHost and http.proxyPort being ignored (Google led me to your question) was that those settings are completely ignored by apache.commons.httpClient because it uses its own sockets, as described here.
http://cephas.net/blog/2007/11/14/java-commons-http-client-and-http-proxies/
I have faced a similar problem recently. First of all, one part of the above answer from Daemon42 explains pretty well, why the bogus proxy server didn't lead to a failure of the program:
if the proxy server cannot be reached at http.proxyHost and http.proxyPort then it simply falls back and tries to do a direct connect. If that succeeds, you'll see no exception thrown which is why your code works without error. You should see a pause while it tries to find the proxy though.
Still, your actual question was, why the proxy server configured via the operating system is not used by the Java application. As stated in the Oracle documentation (https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html), the system proxy settings are not evaluated by Java by default. To do so, you have to set the value of the system property "java.net.useSystemProxies" to the value "true".
You can set that system property on the command line, or you can edit the JRE installation file jre/lib/net.properties, that way you have to change it only once on a given system.
I have a utility where Jmeter sends a request and the utility sends back response to Jmeter. When load increases, the Utility shuts down with an "EXCEPTION_ACCESS_VIOLATION".
Since it is an error, I am not able to handle it in a catch block. I made a second utility to restart the first utility when the error occurs. Below is the code of the second, restart, utility. In this second utility's code, at the second while, my program sometimes hangs. How do I detect this and restart the process?
public static void main(String[] args)
{
String line = null;
String currPID = null;
try
{
while(true)
{
Process process = Runtime.getRuntime().exec("java -XX:+HeapDumpOnOutOfMemoryError -Xms250M -Xmx500M -XX:ErrorFile=NUL ws ");
BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
while ((line = input.readLine()) != null) //Program stucks at this Line
{
if(line.trim().length() != 0)
{
if(line.startsWith("PID"))
{
currPID = line.substring(line.indexOf("#")+1);
}
}
}
System.out.println("Ended");
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
I analysed process through jvisualvm where i found two java process is in running mode when i start second(restart) utility. I can see first utility is restarting regularly because its PID is changing frequently in jvisualvm and same happening in task manager. Everything is going on very well manner.
After sometime i found only one process is in Jvisualvm ie second(restart) utility.
It means first utility JVM is crashed just guessing not sure. Something unusual is happening here. Because if JVM is crashed so It should be restarted.
So i opened task manager and found first utility PID exists there but it is not changing as happening in starting. If i kill the process(first utility) explicitly from task manager.
Seconds utility again restarts first utility same thing happens again, After some time first utility disappeared from jvisualvm, exists in taskmanager and delete process from taskmanager. What needs to do?
Try using .ready() function.
try {
if (stdError.ready())
{
while((line= stdError.readLine()) != null){
logger.error(line);
}
}
}
Do the same for the stdout.
It worked like a charm for me.
Your problem with hanging appears to be at the call to readLine.
readLine is for reading lines. The method will not return until the call is sure the end of line has been reached. It expects either a newline character or the complete cease of communications.
Is your first utility not sending a new line char?
Does your first utility fail to close the stream?
Your while call will hang indefinitely if the answer to both questions is yes.
You might be better off consuming with a custom implementation of the Scanner class.
Try to use getErrorStream() it'll catches the error message, if you use getInputStream() it'll reads only the success message or feedback messages.
for ex: if you execute the following command & read the process message using getInputStream(),
Process process = Runtime.getRuntime().exec("net use u: \\sharedIP\sharedFolder");
BufferedReader input = new BufferedReader(new inputStreamReader(process.getInputStream()));
you can only get feedback messages like "network drive connected successfully" but not the error messages.
if you use getErrorStream() to read the process message it'll read the error messages like "the network drive was not found". when the process executed it'll give a message to either getInputStream() or getErrorStream(). so use both method to read the message from the process, if i'm correct this'll work. I'm just trying to give you an idea but i'm not sure.