ExecutorService for list of object - multithreading

I'm trying add to set some objects that I getting from every link. But objects aren't adding. I receive empty list. Document - jsoup object. What I am doing wrong? Thank you.
public void spinOffThreadsToGetPages() {
Set<WebPage> webPages = new HashSet<>();
ExecutorService executor = Executors.newFixedThreadPool(10);
for (String link : links) {
executor.submit(() -> addWebPagesToSet(webPages, link));
}
executor.shutdown();
}
private void addWebPagesToSet(Set<WebPage> webPages, String link) {
Document document = getDocument(link);
if (document == null) {
return;
}
WebPage webPage = new WebPage(document.title(), link, document.body().text());
webPages.add(webPage);
}

You're not doing anything wrong. The program fires off the threads, then you call ExecutorService::shutdown. The shutdown only occurs once all threads are complete but execution continueS, without blocking the threads execution. If you print out the results as they come back, you'll get output. If you try to print out the results as soon as the threads are submitted, but not yet complete, you'll get nothing back.
Try this:
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MultiThreadedGet {
public static void main(String[] args) throws InterruptedException {
Set<WebPage> webPages = new HashSet<>();
ExecutorService executor = Executors.newFixedThreadPool(10);
Map<String, Document> results = new HashMap<>();
List<String> links = Arrays.asList("https://jsoup.org/cookbook/extracting-data/working-with-urls",
"https://news.ycombinator.com/",
"https://www.spectacleapp.com/",
"https://gradle.org/releases/");
for (String link : links) {
executor.submit(() -> {
try {
addWebPagesToSet(webPages, link);
} catch (IOException e) {
e.printStackTrace();
}
});
}
// executor.awaitTermination(30, TimeUnit.SECONDS);
executor.shutdown();
// premature call to print incompleted thread results
for (WebPage webPage : webPages) {
// You won't see this as the threads take some time to complete.
System.out.println("Premature call: " + webPage.toString());
}
}
private static void addWebPagesToSet(Set<WebPage> webPages, String link) throws IOException {
Document document = Jsoup.connect(link).get();
if (document == null) {
return;
}
WebPage webPage = new WebPage(document.title(), link, document.body().text());
webPages.add(webPage);
System.out.println("WebPage Result: " + webPage.toString());
}
}
class WebPage {
private String title;
private String link;
private String text;
public WebPage(String title, String link, String text) {
this.title = title;
this.link = link;
this.text = text;
}
public String getTitle() {
return title;
}
public String getLink() {
return link;
}
public String getText() {
return text;
}
#Override
public String toString() {
return "title='" + title + '\'' +
", link='" + link + '\'' +
", text='" + text.substring(0, 25) + '\'';
}
}
Output
WebPage Result: title='Gradle | Releases', link='https://gradle.org/releases/', text='Have you checked out the '
WebPage Result: title='Spectacle', link='https://www.spectacleapp.com/', text='Move and resize windows w'
WebPage Result: title='Hacker News', link='https://news.ycombinator.com/', text='Hacker News new | past | '
WebPage Result: title='Working with URLs: jsoup Java HTML parser', link='https://jsoup.org/cookbook/extracting-data/working-with-urls', text='jsoup News Bugs Discussio'
If you need to wait for threads to complete before continuing you can use:
executor.awaitTermination(30, TimeUnit.SECONDS);
which will block the current thread's execution so you can continue with completed results.

Related

How to generate extent report for cucumber + testng framework

How to generate extent report for cucumber + testng framework in such a way that on each scenario failure I can get the screen shot captured, without repeating the code with every scenario in step definition file
I have setup the Testing framework using Cucumber+Testng. However, I need extent reporting but not sure how to achieve it through testNG runner class without actually repeating the code with every scenario of step definition. So the idea is to write code in one place just like using cucumber hooks which will run for each and every scenario.
I Have already tried the approach with TestNG listener with Extent report but with this the drawback is I have to write the code every time for each and every scenario. LIke below I have ITestListnerImpl.java, ExtentReportListner and YouTubeChannelValidationStepDef where for each scenario I have to repeat the loginfo and screencapture methods
Code: ItestListerner.java
package com.testuatomation.Listeners;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;
import com.aventstack.extentreports.ExtentReports;
public class ITestListenerImpl extends ExtentReportListener implements ITestListener {
private static ExtentReports extent;
#Override
public void onFinish(ITestContext arg0) {
// TODO Auto-generated method stub
extent.flush();
System.out.println("Execution completed on UAT env ......");
}
#Override
public void onStart(ITestContext arg0) {
// TODO Auto-generated method stub
extent = setUp();
System.out.println("Execution started on UAT env ......");
}
#Override
public void onTestFailedButWithinSuccessPercentage(ITestResult arg0){
// TODO Auto-generated method stub
}
#Override
public void onTestFailure(ITestResult arg0) {
// TODO Auto-generated method stub
System.out.println("FAILURE");
}
#Override
public void onTestSkipped(ITestResult arg0) {
System.out.println("SKIP");
}
#Override
public void onTestStart(ITestResult arg0) {
System.out.println("STARTED");
}
#Override
public void onTestSuccess(ITestResult arg0) {
// TODO Auto-generated method stub
System.out.println("PASS-----");
}
}
ExtentReportListener. java
package com.testuatomation.Listeners;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.markuputils.ExtentColor;
import com.aventstack.extentreports.markuputils.MarkupHelper;
import com.aventstack.extentreports.reporter.ExtentHtmlReporter;
import com.aventstack.extentreports.reporter.configuration.Theme;
public class ExtentReportListener {
public static ExtentHtmlReporter report = null;
public static ExtentReports extent = null;
public static ExtentTest test = null;
public static ExtentReports setUp() {
String reportLocation = "./Reports/Extent_Report.html";
report = new ExtentHtmlReporter(reportLocation);
report.config().setDocumentTitle("Automation Test Report");
report.config().setReportName("Automation Test Report");
report.config().setTheme(Theme.STANDARD);
System.out.println("Extent Report location initialized . . .");
report.start();
extent = new ExtentReports();
extent.attachReporter(report);
extent.setSystemInfo("Application", "Youtube");
extent.setSystemInfo("Operating System", System.getProperty("os.name"));
extent.setSystemInfo("User Name", System.getProperty("user.name"));
System.out.println("System Info. set in Extent Report");
return extent;
}
public static void testStepHandle(String teststatus,WebDriver driver,ExtentTest extenttest,Throwable throwable) {
switch (teststatus) {
case "FAIL":
extenttest.fail(MarkupHelper.createLabel("Test Case is Failed : ", ExtentColor.RED));
extenttest.error(throwable.fillInStackTrace());
try {
extenttest.addScreenCaptureFromPath(captureScreenShot(driver));
} catch (IOException e) {
e.printStackTrace();
}
if (driver != null) {
driver.quit();
}
break;
case "PASS":
extenttest.pass(MarkupHelper.createLabel("Test Case is Passed : ", ExtentColor.GREEN));
break;
default:
break;
}
}
public static String captureScreenShot(WebDriver driver) throws IOException {
TakesScreenshot screen = (TakesScreenshot) driver;
File src = screen.getScreenshotAs(OutputType.FILE);
String dest = "C:\\Users\\Prateek.Nehra\\workspace\\SeleniumCucumberBDDFramework\\screenshots\\" + getcurrentdateandtime() + ".png";
File target = new File(dest);
FileUtils.copyFile(src, target);
return dest;
}
private static String getcurrentdateandtime() {
String str = null;
try {
DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss:SSS");
Date date = new Date();
str = dateFormat.format(date);
str = str.replace(" ", "").replaceAll("/", "").replaceAll(":", "");
} catch (Exception e) {
}
return str;
}
}
YoutubeChannelValidationsStepDef.java
package com.testautomation.StepDef;
import java.util.Properties;
import org.openqa.selenium.WebDriver;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.GherkinKeyword;
import com.aventstack.extentreports.gherkin.model.Feature;
import com.aventstack.extentreports.gherkin.model.Scenario;
import com.testuatomation.Listeners.ExtentReportListener;
import com.testautomation.PageObjects.YoutubeChannelPage;
import com.testautomation.PageObjects.YoutubeResultPage;
import com.testautomation.PageObjects.YoutubeSearchPage;
import com.testautomation.Utility.BrowserUtility;
import com.testautomation.Utility.PropertiesFileReader;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
public class YoutubeChannelValidationsStepDef extends ExtentReportListener
{
PropertiesFileReader obj= new PropertiesFileReader();
private WebDriver driver;
#Given("^Open Chrome browser with URL$")
public void open_Chrome_browser_with_URL() throws Throwable
{
ExtentTest logInfo=null;
try {
test = extent.createTest(Feature.class, "Youtube channel name validation");
test=test.createNode(Scenario.class, "Youtube channel name validations");
logInfo=test.createNode(new GherkinKeyword("Given"), "open_Chrome_browser_with_URL");
Properties properties=obj.getProperty();
driver=BrowserUtility.OpenBrowser(driver, properties.getProperty("browser.name"), properties.getProperty("browser.baseURL"));
logInfo.pass("Opened chrome browser and entered url");
logInfo.addScreenCaptureFromPath(captureScreenShot(driver));
} catch (AssertionError | Exception e) {
testStepHandle("FAIL",driver,logInfo,e);
}
}
#When("^Search selenium tutorial$")
public void search_selenium_tutorial() throws Throwable
{
ExtentTest logInfo=null;
try {
logInfo=test.createNode(new GherkinKeyword("When"), "search_selenium_tutorial");
new YoutubeSearchPage(driver).NavigateToResultPage("selenium by bakkappa n");
logInfo.pass("Searching selenium tutorial");
logInfo.addScreenCaptureFromPath(captureScreenShot(driver));
} catch (AssertionError | Exception e) {
testStepHandle("FAIL",driver,logInfo,e);
}
}
#When("^Search selenium tutorial \"([^\"]*)\"$")
public void search_selenium_tutorial(String searchString) throws Throwable
{
new YoutubeSearchPage(driver).NavigateToResultPage(searchString);
}
#When("^Click on channel name$")
public void click_on_channel_name() throws Throwable
{
ExtentTest logInfo=null;
try {
logInfo=test.createNode(new GherkinKeyword("When"), "click_on_channel_name");
new YoutubeResultPage(driver).NavigateToChannel();
logInfo.pass("Clicked on the channel name");
logInfo.addScreenCaptureFromPath(captureScreenShot(driver));
} catch (AssertionError | Exception e) {
testStepHandle("FAIL",driver,logInfo,e);
}
}
#Then("^Validate channel name$")
public void validate_channel_name() throws Throwable
{
ExtentTest logInfo=null;
try {
logInfo=test.createNode(new GherkinKeyword("Then"), "validate_channel_name");
String expectedChannelName="1Selenium Java TestNG Tutorials - Bakkappa N - YouTube";
String actualChannelName=new YoutubeChannelPage(driver).getTitle();
Assert.assertEquals(actualChannelName, expectedChannelName,"Channel names are not matching"); //
logInfo.pass("Validated channel title");
logInfo.addScreenCaptureFromPath(captureScreenShot(driver));
System.out.println("closing browser");
driver.quit();
} catch (AssertionError | Exception e) {
testStepHandle("FAIL",driver,logInfo,e);
}
}
}
Your lofInfo is null, should be something like this
#Then("Open Chrome browser with URL")
public void open_Chrome_browser_with_URL() {
try {
logInfo = test.createNode(new GherkinKeyword("Then"), "open_Chrome_browser_with_URL");
//YOUR CODE HERE
logInfo.pass("Chrome opens URL");
}
catch (AssertionError | Exception e) {testStepHandle("FAIL", d, logInfo, e);
}
}

How could I turn this into a thread so it doesn't freeze up my app?

So I was wanting to know how I would go about turning this into a thread? I have tried and failed multiple times. I am about read to give up and just deal with the application freezing while it gets a response.
package me.robert.tb.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
public class HTTPConnect {
private static BufferedReader reader = null;
private static StringBuilder buffer = new StringBuilder();
/**
* This method is used to connect to a website and return its response.
* Mainly used for connecting to API's
*
* #param link
* The URL of the website
* #return The response from the website
*/
public static String getResponse(String link) {
try {
reader = new BufferedReader(new InputStreamReader(new URL(link).openStream()));
int read;
char[] chars = new char[1024];
while ((read = reader.read(chars)) != -1)
buffer.append(chars, 0, read);
} catch (Exception e) {
} finally {
try {
if (reader != null)
reader.close();
} catch (IOException e) {
}
}
return buffer.toString();
}
}
Any help is greatly appreciated!
Here you go. Though you shouldn't really need threads to import 1024 characters. On a few test pages it ran pretty quickly. I think your main issue is trying to make getResponse() static. Anyway, here's your modified code using a thread.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
public class HTTPConnect implements Runnable{
private static BufferedReader reader = null;
private static StringBuilder buffer = new StringBuilder();
private String link;
private String response;
/**
* This method is used to connect to a website and return its response.
* Mainly used for connecting to API's
*
* #param link
* The URL of the website
* #return The response from the website
*/
public HTTPConnect(String input){
link = input;
}
public void run() {
try {
reader = new BufferedReader(new InputStreamReader(new URL(link).openStream()));
int read;
char[] chars = new char[1024];
while ((read = reader.read(chars)) != -1)
buffer.append(chars, 0, read);
} catch (Exception e) {
} finally {
try {
if (reader != null)
reader.close();
response = buffer.toString();
} catch (IOException e) {
}
}
}
public String getResponse(){
return response;
}
public static void main (String[] args){
String website = "http://google.com";
Thread t = new Thread(new HTTPConnect(website));
t.run();
}
}

Create an custom appender in log4j which stores the log in memory

I want to create an custom appender using log4j in java programatically which stores the log in memory(Certain size will be defined for e.g. say DEFAULT_SIZE=20) & as soon as memory is full(there are 20 logs in memory) create an json array of those logs and send it to the server. Along with log message i also want information such as (class, file name,line number,method name,level etc.)
Help is appreciated.!!!
Updated ::
Below is the source code developed by me for the same . Problem which i am facing is i get line number, method name,file name as "?".I dont understand what is the reason.
package com.any.logger;
import java.util.ArrayList;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;
public class Log4jAppender extends AppenderSkeleton {
private static final int DEFAULT_BUFFER_SIZE = 20;
private ArrayList<LoggingEvent> buffer;
private int bufferSize;
public Log4jAppender() {
this.bufferSize = Log4jAppender.DEFAULT_BUFFER_SIZE;
this.buffer = new ArrayList<LoggingEvent>();
}
public void close() {
}
public boolean requiresLayout() {
return false;
}
#Override
protected void append(LoggingEvent loggingEvent) {
synchronized (buffer) {
if (buffer.size() >= bufferSize) {
try {
System.out.println("Hello");
Log4jService service = new Log4jService(new ArrayList<LoggingEvent>
(buffer));
System.out.println("Buff >");
service.start();
} catch (Exception e) {
System.err.println("Failed to write logs");
e.printStackTrace();
} finally {
buffer.clear();
}
}
}
buffer.add(loggingEvent);
}
}
package com.any.logger;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import org.apache.log4j.Level;
import org.apache.log4j.spi.LoggingEvent;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
#SuppressWarnings("rawtypes")
public class Log4jService implements Runnable {
private ArrayList<LoggingEvent> buffer;
private Thread t;
private boolean flag;
public Log4jService(ArrayList<LoggingEvent> buffer) {
this.buffer = new ArrayList<LoggingEvent>(buffer);
this.flag = false;
}
public void start() {
if (!flag) {
this.flag = true;
this.t = new Thread(this);
this.t.start();
}
}
public void run() {
if (flag) {
String json = getLogJson(buffer);
}
}
/**
* Method to get the json log
*
* #param logEvents
* arrayList of log events
* #return an String which is json file
* #throws JSONException
*/
private String getLogJson(ArrayList<LoggingEvent> logEvents) {
System.out.println("In getLogJson");
JSONObject logger = new JSONObject();
try {
JSONArray logs = new JSONArray();
String message = "";
String time = "";
String level = "";
String tag = "";
String file = "";
String exceptionName = "";
String exceptionReason = "";
String line = "";
String clas = "";
String method = "";
int index = 0;
SimpleDateFormat formatter=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (Iterator i = logEvents.iterator(); i.hasNext();) {
LoggingEvent logEvent = (LoggingEvent) i.next();
boolean chk=logEvent.locationInformationExists();
System.out.println("Check :: "+chk);
clas=logEvent.getClass().toString();
JSONObject log = new JSONObject();
message = logEvent.getMessage().toString();
time = String.valueOf(formatter.format(logEvent.getTimeStamp()));
level = logEvent.getLevel().toString();
if (chk) {
System.out.println("hello");
file = logEvent.getLocationInformation().getFileName();
line = logEvent.getLocationInformation().getLineNumber();
method = logEvent.getLocationInformation().getMethodName();
}
if (logEvent.getLevel() == Level.ERROR || logEvent.getLevel() ==
Level.FATAL) {
exceptionReason = message;
}
log.put("message", message);
log.put("time", time);
log.put("level", level);
log.put("tag", tag);
log.put("file", file);
log.put("exceptionName", exceptionName);
log.put("exceptionReason", exceptionReason);
log.put("line", line);
log.put("class", clas);
log.put("method", method);
logs.put(index, log);
index++;
}
JSONObject logsObj = new JSONObject();
logsObj.put("logs", logs);
logger.put("log", logsObj);
System.out.println("Logs Array :: " + logsObj);
System.out.println("Logger Object :: " + logger);
} catch (Exception e) {
e.printStackTrace();
}
return logger.toString();
}
}
I would look at the source code for log4j2 and use an existing appender as a template for my custom appender. SocketAppender and TCPSocketManager may be good places to start.
http://logging.apache.org/log4j/2.0/log4j-core/xref/org/apache/logging/log4j/core/net/TCPSocketManager.html
Currently the buffering is based on the number of bytes, not event count. If you follow the existing appender/manager pattern then in your custom appender manager you will need to have a large enough buffer and flush every 20 events. (Perhaps also flush after some timeout? You may only get 19 events and nothing after that...)
You could also do the buffering in the appender, keep a list of event objects there and only call pass them to the manager to be written after some threshold is reached.
The default Layout for SocketAppender will use java serialization. You'll need to roll your own JasonLayout. The log event object has all the details you mentioned.

ASM ByteCode Instrumentation , Which Method is Executed

I am using ASM Bytecode Library to instrument Java Classes using pre-main.
How do we get the name of the method executed?
Thanks in advance...
In short, there is a name parameter on corresponding visit*() method call. You'll have to produce a more specific example to get more detailed answer.
Attached my Code for your reference
package com.eg.agent;
import java.lang.instrument.Instrumentation;
public class Agent {
private Agent(Instrumentation instrumentation){
}
public static void premain(String agentArgs, Instrumentation inst)
{
EgClassFileTransformer egClassFileTransformer =
new EgClassFileTransformer (agentArgs , inst);
}
}
package com.eg.agent;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import org.objectweb.asm.ClassReader;
public class EgClassFileTransformer implements ClassFileTransformer {
protected String agentArgString = "";
protected Instrumentation instrumentation;
public EgClassFileTransformer(String agentArgs, Instrumentation inst){
agentArgString = agentArgs;
instrumentation = inst;
instrumentation.addTransformer(this);
}
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException
{
//System.out.println("ClassName :"+className);
InputStream in = loader.getResourceAsStream(className.replace('.', '/') + ".class");
try{
ClassReader classReader=new ClassReader(in);
String superClassName = classReader.getSuperName();
String[] interfaces = classReader.getInterfaces();
if(interfaces!=null && interfaces.length > 0){
for(int k=0;k<interfaces.length;k++){
String inface = interfaces[k];
System.out.println(" \t interface :"+inface);
}
}
//System.out.println("superClassName :"+superClassName);
ArrayList thisList = new ArrayList();
thisList.add(superClassName);
ArrayList superList = printSuperClassNames(superClassName , thisList);
System.out.println("className :"+className +" ==>"+ " superList :"+superList);
} catch (IOException e) {
//e.printStackTrace();
System.out.println("[EXECEPTION] ..."+className);
}
return null;
}
public static ArrayList printSuperClassNames(String className, ArrayList list)
{
ClassReader cr=null;
try {
cr = new ClassReader(className);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String superName = cr.getSuperName();
//System.out.println("[superName]"+superName);
if(superName!=null && !superName.equals("java/lang/Object"))
{
list.add(superName);
String superClass = superName.replace('.', '/');
printSuperClassNames(superClass, list);
}
return list;
}
}

Why I am getting the bad length exception when I am running this application?

I want to communicate to a server from J2me app using UDP.However, when I am running the app, I am getting a bad length exception.My codes and output are given below.
client code
import javax.microedition.midlet.MIDlet;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.TextBox;
import javax.microedition.lcdui.TextField;
import javax.microedition.io.Connector;
import javax.microedition.io.Datagram;
import javax.microedition.io.DatagramConnection;
import java.io.IOException;
public class DatagramTest extends MIDlet
implements CommandListener, Runnable
{
private static final int BUF_SIZE = 1024;
private static Command exit = new Command("Exit", Command.EXIT, 1);
private static DatagramTest instance;
private Display display;
private TextBox dgramText;
private DatagramConnection conn;
private Datagram dgram;
private String address = "datagram://myip:9876";
public DatagramTest()
{
super();
instance = this;
}
public DatagramTest(String service)
{
this();
address = service;
}
/**
Returns the single instance of this class. Calling
this method before constructing an object will return
a null pointer.
#return an instance of this class.
*/
public static DatagramTest getInstance()
{
return instance;
}
public void startApp()
{
display = Display.getDisplay(this);
dgramText = new TextBox("Datagram contents",
null,
2048,
TextField.ANY);
dgramText.setCommandListener(this);
display.setCurrent(dgramText);
System.out.println("Starting run....");
run();
System.out.println("Stopping run....");
}
public void run()
{
System.out.println("In run....");
try
{
int maxLength;
conn = (DatagramConnection)Connector.open(address);
maxLength = conn.getMaximumLength();
dgram = conn.newDatagram(1024);
dgram.reset();
conn.send(dgram);
conn.receive(dgram);
byte[] data = dgram.getData();
// Extract the response string.
String str = new String(data);
System.out.println(str);
dgram.reset();
System.out.println("Exit run....");
}
catch (IOException ioe)
{
System.out.println(ioe.getMessage());
ioe.printStackTrace();
quit();
}
return;
}
public void pauseApp()
{
}
void quit()
{
destroyApp(true);
notifyDestroyed();
}
public void destroyApp(boolean destroy)
{
try
{
conn.close();
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
public void display()
{
Display.getDisplay(this).setCurrent(dgramText);
}
public void commandAction(Command c, Displayable d)
{
if (c == exit)
{
quit();
}
}
}
Server code
import java.io.*;
import java.net.*;
class UDPServer
{
public static void main(String args[]) throws Exception
{
DatagramSocket serverSocket = new DatagramSocket(9876);
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
while(true)
{
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
String sentence = new String( receivePacket.getData());
System.out.println("RECEIVED: " + sentence);
InetAddress IPAddress = receivePacket.getAddress();
int port = receivePacket.getPort();
String capitalizedSentence = sentence.toUpperCase();
sendData = capitalizedSentence.getBytes();
DatagramPacket sendPacket =
new DatagramPacket(sendData, sendData.length, IPAddress, port);
serverSocket.send(sendPacket);
}
}
}
Output at clientside
Starting run.... In run.... Bad
datagram length java.io.IOException:
Bad datagram length
at com.sun.midp.io.j2me.datagram.Protocol.receive(Protocol.java:367)
at hello.DatagramTest.run(DatagramTest.java:89)
at hello.DatagramTest.startApp(DatagramTest.java:69)
at javax.microedition.midlet.MIDletProxy.startApp(MIDletProxy.java:43)
at com.sun.midp.midlet.Scheduler.schedule(Scheduler.java:374)
at com.sun.midp.main.Main.runLocalClass(Main.java:466)
at com.sun.midp.main.Main.main(Main.java:120)
Stopping run....
Why I am getting this bad length exception and how do I sort it out?
One thing you need to try is to send and receive datagrams in a separate thread.
The documentation for DatagramConnection.receive() says: "This method blocks until a datagram is received"
You are calling it from inside MIDlet.startApp().
Blocking the application management system thread that calls startApp() is bad practice.

Resources