My scheme: ajax long polling to Tomcat. Tomcat executes selenium "operations".
Im trying to execute selenium scenario from tomcat.
Its working ok but i need to get logs back to js client.
Javascript client partially receives messages from server when selenium working.
Inside some selenium operations im using Thread.sleep(). Maybe mistakes because of this ?
Please tell me why messages partially received (i think) by client
Here is ServerInfoLogger. BaseLogger outputs messages to console and file
public class ServerInfoLogger extends BaseLogger {
public ServerSession clientServerSession;
protected void logToClient(String message) {
super.log(message);
sendMessage(message);
}
// Server.serverSession and Server.clientServerSession not null but messages partially not received by client
private void sendMessage(String message) {
// send message to client
if (Server.serverSession!=null && Server.clientServerSession!=null) {
Server.clientServerSession.deliver(Server.serverSession, "/message", message);
} else {
System.err.println("Server error. Server.serverSession=" + Server.serverSession + " clientServerSession=" + clientServerSession);
}
}
}
Here is selenium scenario
public class Task extends ServerInfoLogger {
public static boolean datesAvailable = false;
private TaskParser parser = new TaskParser();
protected ArrayList<Step> steps = new ArrayList<>();
private WebDriver webDriver;
protected int currentStepIndex = 0;
protected Step currentStep;
private WebDriverFactory webDriverFactory = new WebDriverFactory();
private int currentTryout = 1;
private int maxTryouts = 40;
public Task(ServerSession clientServerSession, String taskData) {
this.clientServerSession = clientServerSession;
logToClient("new task"); // client always receives this message
steps = parser.parse(taskData);
logToClient("steps parsed. total: "+steps.size()); // client always receives this message
start();
}
protected void start() {
createWebDriver();
startStep();
}
protected void startStep() {
currentStep = steps.get(currentStepIndex);
currentStep.setWebDriver(webDriver);
currentStep.clientServerSession = clientServerSession;
boolean stepComplete = false;
try {
stepComplete = currentStep.start();
} catch (StepException e) {
logToClient(e.getMessage()+" step id: "+e.getStepId());
e.printStackTrace();
}
log("step complete = "+stepComplete);
if (stepComplete) {
onStepComplete();
} else {
onStepError();
}
}
private void onStepError() {
currentTryout++;
if (currentTryout > maxTryouts) {
destroyWebDriver();
logToClient("Max tryouts reached"); // client never receives this message
} else {
logToClient("Step not complete. Restarting task. currentTryout=" + currentTryout); // client partially receives this message
restart();
}
}
private void onStepComplete() {
currentStepIndex++;
if (currentStepIndex < steps.size()) {
startStep();
} else {
destroyWebDriver();
taskComplete();
}
}
private void destroyWebDriver() {
webDriver.quit();
webDriver = null;
}
private void taskComplete() {
logToClient("Task complete !!!"); // client **never** receives this message
TaskEvent taskEvent = new TaskEvent(TaskEvent.TASK_COMPLETE);
EventDispatcher.getInstance().dispatchEvent(taskEvent);
}
public void restart() {
logToClient("Task restart");
try {
setTimeout(Application.baseOperationWaitSecondsUntil);
new SwitchToDefaultContentOperation().execute();
} catch(OperationException exception) {
logToClient("Cannot get default content"); // client partially receives this message
}
currentStepIndex = 0;
startStep();
}
private void setTimeout(int seconds) {
webDriver.manage().timeouts().implicitlyWait(seconds, TimeUnit.SECONDS);
}
private void createWebDriver() {
webDriver = webDriverFactory.getDriver(BrowserType.CHROME).getDriver();
}
public int getCurrentStepIndex() {
return currentStepIndex;
}
}
Here is creation of logger
private void createLogger() {
Date currentDate = new Date();
String logFilePostfix = currentDate.getMonth()+"_"+currentDate.getDate()+"-"+currentDate.getHours()+"_"+currentDate.getMinutes()+"_"+currentDate.getSeconds();
logger = Logger.getLogger(appName);
logger.setUseParentHandlers(false);
FileHandler fh;
SimplestFormatter formatter = new SimplestFormatter();
try {
fh = new FileHandler("C:\\consultant\\logs\\log_"+logFilePostfix+".txt");
logger.addHandler(fh);
fh.setFormatter(formatter);
} catch (SecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Selenium operation with Thread.sleep()
public class SwitchToMainFrameOperation extends BaseOperation {
private WebElement mainIframe;
private WebDriverWait wait;
#Override
public boolean execute() throws OperationException {
switchToRoot();
sleepThread();
log("switchToMainIFrame by xPath "+Page.getMainIframeXPath()); // log to console and file
wait = new WebDriverWait(webDriver, Application.baseOperationWaitSecondsUntil);
try {
mainIframe = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(Page.getMainIframeXPath())));
webDriver.switchTo().frame(mainIframe);
log("main frame switch OK"); // log to console and file
} catch(StaleElementReferenceException exception) {
log("main frame switch error. StaleElementReferenceException - trying again"); // log to console and file
wait = null;
sleepThread();
execute();
}
return true;
}
private void switchToRoot() {
log("switch to root");
webDriver.switchTo().defaultContent();
}
private void sleepThread() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Related
I'm taking my first steps with Java Sockets and Threads.
I want to try make synchonized connection with serwer where multiple threades adds their request to the queue and signle thread send all this request. In the meantime other threads wait for there resoults.
How it's work:
Client ask servert to log in by caling method
User user = logIn("sdasd");
public User logIn(String name){
System.out.println("!Log in");
//Function create request
RequestHandler<User> request = new RequestHandler<>("logIn", name, out, results);
//Request is added to queue
requestQueue.addLast(request);
RequestStatus status;
//Thread who call this function wait for request to be handle (changed status)
while (true){
status = request.getStatus();
System.out.println(status);
if (status == RequestStatus.SUCCESSFUL) {
System.out.println("Try to get result: ");
User user = request.result();
System.out.println(user.getName());
return request.result();
}
if(status == RequestStatus.FAILED) {
return null;
}
}
}
In the meantime other thread send request to server:
new Thread(new Runnable() {
#Override
public void run() {
while(isConnected()){
//is request to be handle?
if(requestQueue.size() != 0){
//remove request form queue
RequestHandler request = (RequestHandler) requestQueue.removeFirst();
//change request status
request.setStatus(RequestStatus.IN_PROGRESS);
System.out.println("!Request: ");
System.out.println(request.getStatus());
//process request
request.request();
//change request status to finished
request.setStatus(RequestStatus.SUCCESSFUL);
System.out.print("!Request end: ");
System.out.println(request.getStatus());
}
}
Iterator<Request> iterator = requestQueue.iterator();
for (Iterator<Request> it = iterator; it.hasNext(); ) {
Request request = it.next();
request.setStatus(RequestStatus.FAILED);
}
}
}).start();
Inside class RequestHandler is process this code:
#Override
public void request() {
try {
//send commend
out.writeObject(requestCommend);
//wait for result (other thread handle this functionality)
while(!results.containsKey(commend)){}
//attach result
result = (T) results.remove(commend);
} catch (IOException e) {
e.printStackTrace();
}
}
When the request is send to the server other thread wait for response for the server and add result to the HashMap:
new Thread(new Runnable() {
#Override
public void run() {
while(isConnected()) {
try {
String commend = (String) in.readObject();
if(commend.charAt(0) == '#') { // # mean its result of request
Object object = in.readObject();
//This is debug case to see everything work properly
if(object == null){
System.out.println("!I am null");
}else{
System.out.println("I am user: " +((User) object).getName());
}
System.out.println(commend);
results.put(commend, object);
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}).start();
This is it. Required code for this question:
public class ServerConnection extends Socket{
public static final int PORT = 8888;
private ObjectInputStream in;
private ObjectOutputStream out;
private LinkedList<Request> requestQueue;
private ConcurrentHashMap<String, Object> results;
public ServerConnection() throws IOException{
super("localhost", PORT);
System.out.println("Connected to the server.");
in = new ObjectInputStream(getInputStream());
out = new ObjectOutputStream(getOutputStream());
requestQueue = new LinkedList<>();
results = new ConcurrentHashMap<>();
new Thread(new Runnable() {
#Override
public void run() {
while(isConnected()){
if(requestQueue.size() != 0){
RequestHandler request = (RequestHandler) requestQueue.removeFirst();
request.setStatus(RequestStatus.IN_PROGRESS);
System.out.println("!Request: ");
System.out.println(request.getStatus());
request.request();
request.setStatus(RequestStatus.SUCCESSFUL);
System.out.print("!Request end: ");
System.out.println(request.getStatus());
}
}
Iterator<Request> iterator = requestQueue.iterator();
for (Iterator<Request> it = iterator; it.hasNext(); ) {
Request request = it.next();
request.setStatus(RequestStatus.FAILED);
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
while(isConnected()) {
try {
String commend = (String) in.readObject();
if(commend.charAt(0) == '#') { // # mean its result of request
Object object = in.readObject();
//This is debug case
if(object == null){
System.out.println("!I am null");
}else{
System.out.println("I am user: " +((User) object).getName());
}
System.out.println(commend);
results.put(commend, object);
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}).start();
}
public User logIn(String name){
System.out.println("!Log in");
RequestHandler<User> request = new RequestHandler<>("logIn", name, out, results);
requestQueue.addLast(request);
RequestStatus status;
while (true){
status = request.getStatus();
System.out.println(status);
if (status == RequestStatus.SUCCESSFUL) {
System.out.println("Try to get result: ");
User user = request.result();
System.out.println(user.getName());
return request.result();
}
if(status == RequestStatus.FAILED) {
return null;
}
}
}
public ArrayList<Room> getListOfRooms(){
Request<ArrayList<Room>> request = new RequestHandler<>("listOfRooms", out, results);
requestQueue.addLast(request);
while (true){
RequestStatus status = request.getStatus();
if (status == RequestStatus.SUCCESSFUL)
return request.result();
if(status == RequestStatus.FAILED) {
return null;
}
}
}
}
RequestHandler looks like this:
public class RequestHandler<T> implements Request<T>{
private T result;
private RequestStatus status = RequestStatus.NEW;
private ObjectOutputStream out;
private String commend;
private String requestCommend;
private ConcurrentHashMap<String, Object> results;
public RequestHandler(String commend, String parameters, ObjectOutputStream out, ConcurrentHashMap<String, Object> results) {
this.commend = "#" + commend;
this.requestCommend = "?" + commend + ":" + parameters;
this.out = out;
this.results = results;
}
public RequestHandler(String commend, ObjectOutputStream out, ConcurrentHashMap<String, Object> results) {
this.commend = "#" + commend;
this.requestCommend = "?" + commend;
this.out = out;
this.results = results;
}
#Override
public void request() {
try {
out.writeObject(requestCommend);
while(!results.containsKey(commend)){}
result = (T) results.remove(commend);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public T result() {
return result;
}
#Override
public RequestStatus getStatus() {
return status;
}
#Override
public void setStatus(RequestStatus status) {
this.status = status;
}
}
The output looks like this WHEN ITS WORK:
Connected to the server.
!Log in
NEW
IN_PROGRESS
...
IN_PROGRESS
!Request: IN_PROGRESS
IN_PROGRESS
...
IN_PROGRESS
I am user: sdsad
#logIn
IN_PROGRESS
IN_PROGRESS
SUCCESSFUL
!Request end: SUCCESSFUL
Try to get result:
sdsad
But when I COMMENT one debug msg I got this:
Connected to the server.
!Log in
!Request: IN_PROGRESS
I am user: dfdsfsdf4324
#logIn
!Request end: SUCCESSFUL
And the loop while(true) never end becouse I got always status IN_PROGRESS.
That's why I want to ask you why it's happen? Is Java have some weird way to optimalize output of functions to make is faster and is it thinking if it was reapet milion times so it has to be this state always?
Update: came up with new error about the provided java class
I have a tutorial for building an app for an external barcode scanner(use USB port) by using Java + provided Jar Library. I'm trying to build the same app by using the Xamarin.Forms and that Jar Library(through BindingsLibrary Project). However, I got an error
"Java.Lang.NoClassDefFoundError: " when I compiled my code. Does anybody have an idea about what I'm doing wrong?
This my java classes:
The USBScanFactory
package com.unistrong.qrcode;
import com.unistrong.pin.GOPOManager;
public class USBQRscanFactory {
private static USBQRscanFactory factory = new USBQRscanFactory();
static boolean mIsScanContinue = false;
private GOPOManager mGopoManager = GOPOManager.getInstance();
private OnScanListener mScanListener;
private QRScanManagerJNI qrScanManagerJNI;
private USBQRscanFactory() {
}
public static USBQRscanFactory createInstance() {
return factory;
}
public void init(OnScanListener onScanListener) {
this.mGopoManager.Pin11_High();
this.qrScanManagerJNI = new QRScanManagerJNI(onScanListener);
this.qrScanManagerJNI.callbackInit();
}
public void enableAddKeyValue(int i) {
QRScanManagerJNI.AddKeyValue(i);
}
public void open() {
this.mGopoManager.Pin11_Low();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
QRScanManagerJNI.OpenDev();
}
public void powerOn() {
this.mGopoManager.Pin11_High();
this.mGopoManager.openPower5V_3V3();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void powerOff() {
this.mGopoManager.Pin11_High();
this.mGopoManager.closePower5V_3V3();
}
public void scan_start() {
QRScanManagerJNI.QRScan();
}
On ScanListener:
package com.unistrong.qrcode;
public interface OnScanListener {
void scanReport(byte[] bArr);
void statusReport(int i);
}
And here is my code on Xamain:
public class OnScanListener : Java.Lang.Object, IOnScanListener
{
H myH = new H();
public void ScanReport(byte[] byteArray)
{
lock (myH)
{
if (null != byteArray && byteArray.Length > 0)
{
myH.SendMessage(myH.ObtainMessage(0, byteArray));
}
}
}
public void StatusReport(int i)
{
lock (myH)
{
myH.SendEmptyMessage(i);
}
}
}
#endregion
public MainPage()
{
usbScan = USBQRscanFactory.CreateInstance();
InitializeComponent();
}
int count = 0;
private void scanBtn_Clicked(object sender, EventArgs e)
{
count++;
//usbScan.Init(OnScanListener);
OnScanListener myOnScanListener = new OnScanListener();
usbScan.PowerOn();
usbScan.Init(myOnScanListener);
Barcode.Text = "";
openScanner(true);
usbScan.Scan_start();
}
//Open Scanner
private void openScanner(bool open)
{
if (open == mWorkingStateFlag) return;
if (open)
{
try
{
Java.Lang.Thread.Sleep(50);
usbScan.Open();
usbScan.EnableAddKeyValue(0);
}
catch (Java.Lang.InterruptedException e)
{
// TODO Auto-generated catch block
e.PrintStackTrace();
}
}
}
I have a successfully running ProcessBuilder running which scans a DVB-T for channel broadcasts on a server and I want the output going to a web page.
The server code as follows:
private static StringBuilder scan_output = null;
private static String scan_result = "";
#Override
public boolean scanByBroadcaster(String user, String broadcaster) {
UserAccountPermissions perm = validateUserEdit(user); // allowed to run scan?
if (perm == null) return false;
String[] commands = {
"/usr/bin/scan",
dvbDir + broadcaster,
"-o",
"zap",
"-U",
"-q",
"-a",
"5",
">",
LoginConstants.loc_dvb_scanfile
};
System.out.println("Scan by broadcast: " + broadcaster);
scan_output = new StringBuilder();
new ScanThread(commands).start();
return false;
}
// runs the scan independant and the IO capture
private static class ScanThread extends Thread {
String[] commands = null;
public ScanThread(String[] commands) {
this.commands = commands;
}
public void run() {
ProcessBuilder pb = new ProcessBuilder(commands);
Process process;
try {
System.out.println("Scan thread running");
process = pb.start();
IOScanOutputHandler handler = new IOScanOutputHandler(process.getInputStream());
handler.start();
process.waitFor();
} catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
} catch (InterruptedException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
//scan_output = null;
System.out.println("Scan thread finished");
}
}
// background thread to capture output of scan (as it arrives)
// this only captures the final scan results though
private static class IOScanOutputHandler extends Thread {
private InputStream inputStream;
IOScanOutputHandler(InputStream inputStream) {
this.inputStream = inputStream;
}
public void run() {
Scanner br = null;
try {
System.out.println("Scan thread IO capture running");
br = new Scanner(new InputStreamReader(inputStream));
String line = null;
while (br.hasNextLine()) {
line = br.nextLine();
scan_output.append(line + System.getProperty("line.separator"));
}
} finally {
br.close();
}
System.out.println("Scan thread IO capture finished");
scan_result = scan_output.toString();
scan_output = null;
}
}
// polled by web interface every second
#Override
public String pollScanResult(String user) {
if (validateUserEdit(user) == null) return null;
StringBuilder sb = scan_output; // grab instance
if (sb == null) return null;
return sb.toString();
}
The final output I actually get is what goes into "LoginConstants.loc_dvb_scanfile" and not this output:
ERROR: invalid enum value '7378'
ERROR: invalid enum value '3300'
ERROR: invalid enum value '0'
ERROR: invalid enum value '8MHz'
ERROR: invalid enum value '2/3'
ERROR: invalid enum value 'NONE'
ERROR: invalid enum value 'QAM2'
>>> tune to: 706000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_2_3:FEC_AUTO:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_32:HIERARCHY_NONE
>>> tune to: 778000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_2_3:FEC_1_2:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_32:HIERARCHY_NONE
>>> tune to: 2:INVERSION_AUTO:BANDWIDTH_AUTO:FEC_AUTO:FEC_AUTO:QAM_AUTO:TRANSMISSION_MODE_AUTO:GUARD_INTERVAL_AUTO:HIERARCHY_AUTO
__tune_to_transponder:1910: ERROR: Setting frontend parameters failed: 22 Invalid argument
>>> tune to: 2:INVERSION_AUTO:BANDWIDTH_AUTO:FEC_AUTO:FEC_AUTO:QAM_AUTO:TRANSMISSION_MODE_AUTO:GUARD_INTERVAL_AUTO:HIERARCHY_AUTO
__tune_to_transponder:1910: ERROR: Setting frontend parameters failed: 22 Invalid argument
>>> tune to: 770000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_1_2:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_32:HIERARCHY_NONE
>>> tune to: 698000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_1_2:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_32:HIERARCHY_NONE
>>> tune to: 746000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_1_2:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_32:HIERARCHY_NONE
>>> tune to: 762000000:INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_3_4:FEC_1_2:QAM_16:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_32:HIERARCHY_NONE
WARNING: filter timeout pid 0x0011
WARNING: filter timeout pid 0x0000
WARNING: filter timeout pid 0x0010
The scan gets started from GWT client side via RPC calls. For brevity, here's that code:
private void runScanQuick() {
server.checkEditAccess(user, new AsyncCallback<Boolean>() {
#Override
public void onFailure(Throwable caught) {
log.info("runScanQuick server failure");
}
#Override
public void onSuccess(Boolean result) {
if (result == false) return; // not allowed to run scan
final DialogBox dia = new DialogBox();
final Frame frame = new Frame(url_base + url_ext_scanbybroadcaster);
frame.addLoadHandler(new LoadHandler() {
#Override
public void onLoad(LoadEvent event) {
String broadcaster = scan_country.getSelectedItemText() + "-" + scan_broadcaster.getSelectedItemText();
log.info("Scan file: " + broadcaster);
Document doc = IFrameElement.as(frame.getElement()).getContentDocument();
doc.getElementById("broadcaster").appendChild(new HTML(broadcaster).getElement());
Button okay = Button.wrap(doc.getElementById("okay"));
Button cancel = Button.wrap(doc.getElementById("cancel"));
cancel.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
dia.hide();
}
});
okay.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
dia.hide();
runScanQuickStart();
}
});
}
});
frame.setSize("500px", "500px");
dia.add(frame);
dia.setGlassEnabled(true);
dia.setStyleName("");
dia.center();
dia.show();
}
});
}
private void runScanQuickStart() {
final DialogBox dia = new DialogBox();
final Frame frame = new Frame(url_base + url_ext_scanbroadcasterprogress);
frame.addLoadHandler(new LoadHandler() {
#Override
public void onLoad(LoadEvent event) {
Document doc = IFrameElement.as(frame.getElement()).getContentDocument();
String broadcaster = scan_country.getSelectedItemText() + "-" + scan_broadcaster.getSelectedItemText();
doc.getElementById("title").appendChild(new HTML(broadcaster).getElement());
Button okay = Button.wrap(doc.getElementById("okay"));
final TextArea area = TextArea.wrap(doc.getElementById("textarea"));
final Timer timer = new Timer() {
#Override
public void run() {
server.pollScanResult(user, new AsyncCallback<String>() {
#Override
public void onFailure(Throwable caught) {
cancel();
}
#Override
public void onSuccess(String result) {
if (result == null) cancel();
else {
area.setText(result);
}
log.info("Polled for scan result");
}
});
}
};
okay.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
timer.cancel();
dia.hide();
}
});
server.scanByBroadcaster(user, broadcaster, new AsyncCallback<Boolean>() {
#Override
public void onFailure(Throwable caught) {
log.info("runScanQuickStart server call failed");
}
#Override
public void onSuccess(Boolean result) {
if (result == false) return;
timer.scheduleRepeating(1000);
}
});
}
});
frame.setSize("740px", "500px");
dia.add(frame);
dia.setGlassEnabled(true);
dia.setStyleName("");
dia.center();
dia.show();
}
Everything is working fine apart from the fact I don't know how to fetch the live output from the ProcessBuilder.
Does anyone know how to grab the live output so that I can show live feedback in the web page?
I'm thinking that maybe it could be either stderr, stdout or something.
After two days of struggling with this and then posting a question, I figured it out half an hour later. Grr...
I changed this over to get the Error stream:
//IOScanOutputHandler handler = new IOScanOutputHandler(process.getInputStream());
IOScanOutputHandler handler = new IOScanOutputHandler(process.getErrorStream());
And in the server function scanByBroadcaster(), I just added return true which enabled the client side timer to start polling.
Phew!!!
This pertains to my earlier post "http://stackoverflow.com/questions/8788825/linux-udp-server-unreachable-from-window-7", which has been solved. Now I am moving to my original job of connecting AVD to Linux server.
I am using the following code for connecting to the server
import java.net.*;
class UDPClient {
public final static int DesitnationPort = 9999;
private int mCounter;
private DatagramSocket mClientSocket;
private InetAddress mServerIPAddress;
private byte[] mDataBuffer;
private DatagramPacket mSendPacket;
private DatagramPacket mReceivePacket;
//Constructor
public UDPClient() {
//Time to make the private data good one
mCounter =1;
try {
mServerIPAddress = InetAddress.getByName("192.168.2.2");
}
catch(UnknownHostException e)
{
System.out.println("Host cannot be resolved :( ");
}
System.out.println("Host has been resolved The IP is valid one ");
try {
mClientSocket = new DatagramSocket();
}
catch(SocketException e)
{
System.out.println("Socket could not be created :( ==> " + e.getMessage());
}
System.out.println("Socket has been created ");
String temp = "This is from the Client == To my Dear Sever :) counter = " + mCounter;
mDataBuffer = temp.getBytes();
mSendPacket = new DatagramPacket(mDataBuffer, mDataBuffer.length, mServerIPAddress, DesitnationPort);
System.out.println("Datagram has been made now ");
System.out.println("Data ==>"+ mSendPacket.getData());
System.out.println("Data ==>"+ mSendPacket.getPort());
System.out.println("Data ==>"+ mSendPacket.getSocketAddress());
System.out.println("Data ==>"+ mSendPacket.getLength());
}
public void SendDataToServer(){
try {
if(!mClientSocket.isClosed()) {
String temp = "This is from the Client == To my Dear Sever :) counter = " + mCounter;
mDataBuffer = temp.getBytes();
mSendPacket = new DatagramPacket(mDataBuffer, mDataBuffer.length, mServerIPAddress, DesitnationPort);
mClientSocket.send(mSendPacket);
System.out.println("Send the packet");
mCounter++;
}
else {
System.out.println("Socket is closed");
}
}
catch(Exception e)
{
System.out.println("Could not send the data :( ==> " + e.getMessage());
}
}
public void ReceiveDataFromServer() {
byte[] tembuff = new byte[1024];
mReceivePacket = new DatagramPacket(tembuff, tembuff.length);
try {
if(!mClientSocket.isClosed()) {
mClientSocket.receive(mReceivePacket);
}
else {
System.out.println("Socket is closed");
}
}
catch(Exception e)
{
System.out.println("Could not Receive the data :( ");
return;
}
String data = new String(mReceivePacket.getData());
System.out.println(" Received the Data => " + data);
}
}
This code works well when I simply use the class in java program like this :-
class TryingWithClient {
public static void main(String a[]) {
UDPClient mClient = new UDPClient();
while(true) {
System.out.println("While Starting");
mClient.SendDataToServer();
mClient.ReceiveDataFromServer();
}
}
}
When I use the same code in AVD project I get a Null pointer exception at the following line :-
public void SendDataToServer(){
try {
if(!mClientSocket.isClosed()){ //<==# this call Null exception occurs
After browsing internet & android development sites I came to conclusion that I am missing the GMS / GPS functionality which I added to my AVD. Still I am unable to get any clue about this.
Here is my code which calls the above UDPClient.
public class StreamingProjectActivity extends Activity {
/** Called when the activity is first created. */
//All buttons
//private static final String LOG_TAG = "StreamingTest";
private StreamButton mStreamButton = null;
private UDPClient mClient= null;
class StreamButton extends Button {
boolean mStartStreaming = true;
OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {
onStream(mStartStreaming);
if (mStartStreaming) {
setText("Stop Streaming");
} else {
setText("Start recording");
}
mStartStreaming = !mStartStreaming;
}
};
public StreamButton(Context ctx) {
super(ctx);
setText("Start Streaming");
setOnClickListener(clicker);
}
}//class StreamButton Ends
#Override
public void onCreate(Bundle icicle) {
try {
mClient = new UDPClient();
System.out.println("==========> Client created sucessfully :) <====== ");
super.onCreate(icicle);
LinearLayout ll = new LinearLayout(this);
mStreamButton = new StreamButton(this);
ll.addView(mStreamButton,
new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
setContentView(ll);
System.out.println("Trying Step 2 now ");
}
catch(Exception e)
{
System.out.println("Activity could not be launched :( ");
}
}
//public StreamingTest()
public StreamingProjectActivity(){
System.out.println("Constructor ====>");
System.out.println("Constructor <====");
}//Constructor
private void onStream(boolean start) {
if (start)
{
mClient.SendDataToServer();
mClient.ReceiveDataFromServer();
try
{
Thread.sleep(4000);
}catch (InterruptedException ie)
{
System.out.println(ie.getMessage());
}
}
}//onStream
}
Kindly help.
Ok, first of all: never ever print a catched exception with System.out.println("some msg " + e.getMessage()); Please use Log.e(TAG, "my message", e); for that. So you will actually see a stack trace.
Second: I bet that this code throws an error (check if you see the print in your LogCat output):
try {
mClientSocket = new DatagramSocket();
} catch(SocketException e) {
System.out.println("Socket could not be created :( ==> " + e.getMessage());
}
That is the only reason that mClientSocket still might be null. As this call might go wrong, you should consider checking for null before you check if the socket is closed.
The problem in my earlier solution was that I was mixing the GUI & network operations in the same thread which is called "StricMode.ThreadPolicy" (although, my problem is only part of what is mentioned in the jargon).
I was getting these exceptions "android.os.NetworkOnMainThreadException & android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1099) " which I could make out only after I applied WarrenFaith's suggestion (Thanks Warren).
These are thrown only on violation of "StricMode".
Solution : Simply separate the UI work from the network. I had to write the following code for this :
enum ClientThreadStates {
eUndefined,
eStopped,
eRunning,
eIdle,
eSendToServer,
eReadFromServer
}
public class ClientThread extends Thread {
private UDPClient mClient= null;
private ClientThreadStates mStateOfTheThread = ClientThreadStates.eUndefined;
private static String mLOG_TAG;
public ClientThread(String s){
mLOG_TAG = s;
mStateOfTheThread = ClientThreadStates.eStopped;
mClient = new UDPClient(s);
start();
}//constructor
public void SetState(ClientThreadStates paramState) {
mStateOfTheThread = paramState;
}
public ClientThreadStates GetState() {
return mStateOfTheThread;
}
private void Action(ClientThreadStates s) {
synchronized(s) {
switch(mStateOfTheThread) {
case eRunning: //fall
case eIdle: break;
case eSendToServer: mClient.SendDataToServer(); break;
case eReadFromServer: mClient.ReceiveDataFromServer(); break;
}
try {
mStateOfTheThread.wait();
}
catch( InterruptedException e ){
Log.e(mLOG_TAG, "Got Exception at wait <==", e);
}
}
}
public void run() {
mStateOfTheThread = ClientThreadStates.eRunning;
System.out.println("In Thread.run .. The State is " + mStateOfTheThread);
while(ClientThreadStates.eStopped.compareTo(mStateOfTheThread) < 0){ //state >stopped
Action(mStateOfTheThread);
}//while
}//run
}//class ClientThread
Finally synchronize on the two threads on the state like this :
private void onStream(boolean start) {
ClientThreadStates State = mClientThread.GetState();
synchronized(State) {
if (start) {
mClientThread.SetState(ClientThreadStates.eSendToServer);
}
else {
mClientThread.SetState(ClientThreadStates.eReadFromServer);
}
try {
State.notify();
}
catch( IllegalMonitorStateException e ) {
Log.e(LOG_TAG, "Got Exception # notify <==", e);
}
}
}//onStream
}//StreamingProjectActivity
Now the code runs perfectly.
Thanks.
Ashutosh
I am trying to "connect" two classes together, MyJFrame and MySerialPort, using the interface SerialPortListener, but I am clueless as how to do it. The reason I am doing this is because yesterday I had a problem assigning data from a serial port buffer to a global String (finalString), in the MySerialPort class. This string should be returned to MyJFrame where a label displays it. The problem was that my label would display finalString before anything
was assigned to finalString, since classes were running in different threads. I posted the question on the forum and received a suggestion to use interface to connect their threads, and I modified the code according. Where do I use the keyword implements SerialPortListener and how do I get the value?
SerialPortListener Interface code
public interface SerialPortListener {
void stringReveivedFromSerialPort(String s);
}
MyJFrame class code
public class MyJFrame extends JFrame{
public MySerialPorts msp = new MySerialPorts();
public MyJFrame(){
initComponents();//draws GUI components
initSerialPorts();//initializes serial ports
}
private void initSerialPorts(){
msp.getPortName();//gets serial port's name (in this example COM1)
msp.openPort();//opens the communication for port COM1
}
private String firmwareVersion(){
//This is the method I call when I want to get the Firmware Version
msp.getFirmwareVersion();//sends command to receive reply from serial device
lblFirmwareVersion.setText();//label that prints the firmware version String
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new MainJFrame().setVisible(true);
}
});
}
private JLabel lblFirmwareVersion;
}
MySerialPort class code
public class MySerialPort {
//this method is using the jSSC API (java simple serial connector)
//http://code.google.com/p/java-simple-serial-connector/
private SerialPort serialPort;
private int iBaudRate = SerialPort.BAUDRATE_57600;
private int iDataBits = SerialPort.DATABITS_8;
private int iStopBits = SerialPort.STOPBITS_1;
private int iParity = SerialPort.PARITY_NONE;
private String portName = "";
// private String finalString = "";
// private StringBuilder sbBuffer = new StringBuilder();
private List<SerialPortListener> portListeners = new ArrayList<SerialPortListenerInterface>();
public void addMyPortListener(SerialPortListener listener) {
portListeners.add(listener);
}
public void removeMyPortListener(SerialPortListener listener) {
portListeners.remove(listener);
}
public void getFirmwareVersion() {
sendPortCommand("<VersFV1A2>\r\n");
}
// public String returnFinalString() {
// return finalString;
// }
public void getPortName() {
String[] ports = SerialPortList.getPortNames();
portName = ports[0];
}
public void openPort() {
serialPort = new SerialPort(portName);
try {
if (serialPort.openPort()) {
if (serialPort.setParams(iBaudRate, iDataBits, iStopBits, iParity)) {
serialPort.addEventListener(new Reader(), SerialPort.MASK_RXCHAR
| SerialPort.MASK_RXFLAG
| SerialPort.MASK_CTS
| SerialPort.MASK_DSR
| SerialPort.MASK_RLSD);
} else {
//Error Message - Can't set selected port parameters!
serialPort.closePort();
}
} else {
//Error Message - Can't open port!
}
} catch (SerialPortException | HeadlessException ex) {
//Error Message - Can't open port! - Do nothing
}
}
private void sendPortCommand(String sSendPortCommand) {
if (sSendPortCommand.length() > 0) {
try {
serialPort.writeBytes(sSendPortCommand.getBytes());
} catch (Exception ex) {
//Error Message - Error occured while sending data!
}
}
}
private class Reader implements SerialPortEventListener {
private String sBuffer = "";
#Override
public void serialEvent(SerialPortEvent spe) {
if (spe.isRXCHAR() || spe.isRXFLAG()) {
if (spe.getEventValue() > 0) {
try {
//Read chars from buffer
byte[] bBuffer = serialPort.readBytes(spe.getEventValue());
sBuffer = new String(bBuffer);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
for (SerialPortListenerInterface listener : portListeners) {
listener.stringReveivedFromSerialPort(sBuffer);
}
}
});
// The following is the code I had prior to suggestion of using invokeLater instead of invokeAndWait
//
// sbBuffer.setLength(0);
//
// SwingUtilities.invokeAndWait(
// new Runnable() {
//
// #Override
// public void run() {
// sbBuffer.append(sBuffer);
// }
// });
//
// finalString = new String(sbBuffer);
} catch (Exception ex) {
}
}
}
}
}
}
Here's some code that you could add to your initSerialPorts() method, and which would open a dialog box displaying the text received from the serial port:
msp.addMyPortListener(new SerialPortListener() {
#Override
public void stringReveivedFromSerialPort(String s) {
JOptionPane.showMessageDialog(MyJFrame.this, s);
}
});
It creates an anonymous SerialPortListener instance, which displays a dialog box containing the received text as message, and adds it to your MySerialPort msp instance.
I believe that you want your MyJFrame class to implement SerialPortListener:
public class MyJFrame extends JFrame implements SerialPortListener {
/* blah */
#Override
public void stringReveivedFromSerialPort(String s) {
lblFirmwareVersion.setText(s);
}
/* blah */
}