Applet processing a file works locally but fails in website - java

I've been bashing my head in on this problem for a few days now. I've done my full share of Googling, and I'm hoping I can find someone here that is more experienced than I (not hard to find haha) that can decipher my problem.
Scenario: I developed a Java Applet that implements a Swing GUI. Background work: The Applet gathers records from a large "phone book" excel file (.csv) and stores them in a Map data structure. The phone book contains about 106,000 records, and on the 34,586th record, I get an ArrayIndexOutOfBoundsException that I cannot make sense of. The exception only occurs when I'm running the applet on my personal website. The applet runs perfectly fine with no errors while testing in my IDE (NetBeans) and running the .html file (the one that contains the applet) on my local machine. The output and exception that is thrown while running on my website is as follows (I cut most of the records to save space):
Java Console
Kary,Webber,2826 East 12th Ave.,Memphis,TN,38168,901-749-1834
Erinn,Rocha,2132 East Main Ave.,Memphis,TN,38168,865-414-5105
Gina,Lane,71 South First St. Apt. 11,Memphis,TN,38168,731-485-1129
Patsy,Hart,661 East 11th St.
java.lang.ArrayIndexOutOfBoundsException: 3
at Implementation.PersonnelDatabase.addRecordFromFields(PersonnelDatabase.java:192)
at Implementation.PersonnelDatabase.initDBFromFile(PersonnelDatabase.java:215)
at Implementation.PersonnelDatabase.processData(PersonnelDatabase.java:239)
at Implementation.PersonnelDatabaseApplet$2.doInBackground(PersonnelDatabaseApplet.java:78)
at Implementation.PersonnelDatabaseApplet$2.doInBackground(PersonnelDatabaseApplet.java:69)
at javax.swing.SwingWorker$1.call(Unknown Source)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at javax.swing.SwingWorker.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
As you can see, on the 34,586th record (beginning with Patsy,Hart), it outputs midway through her address. The full record is as follows: Patsy,Hart,661 East 11th St. Apt. 195,Memphis,TN,38168,555-555-5555 .
Below are the sections of code that are most logically influenced by the exception.
Object tag in HTML file
<object type="application/x-java-applet" height="400" width="300">
<param name="codebase" value="classes" />
<param name="code" value="Implementation/PersonnelDatabaseApplet.class" />
<param name="archive" value="PersonnelDatabase.jar" />
Applet failed to run. No Java plug-in was found.
</object>
PersonnelDatabase class (processes background data):
/*
* Create a new record using an appropriately ordered set of fields and add it to the data base
*/
public void addRecordFromFields(String[] fields)
{
// Read record attributes in, one at a time
Record thisRecord = new Record();
thisRecord.setFirstName(fields[0]);
thisRecord.setLastName(fields[1]);
thisRecord.setAddress(fields[2]);
thisRecord.setCity(fields[3]);
thisRecord.setState(fields[4]);
thisRecord.setZipCode(fields[5]);
thisRecord.setPhoneNo(fields[6]);
addRecord(thisRecord);
}
// O( n )
/**
* Destroy the current data base and load new data from a file.
* #param filename the file to use as a source
* #throws IOException: Either file not found or IO error
*/
public void initDBFromFile(URL url) throws IOException
{
// Open and read the file
InputStream in = url.openStream();
BufferedReader filein = new BufferedReader(new InputStreamReader(in));
// Read record file, parse lines, and add records to data base
String line = filein.readLine();
while(line != null) {
System.err.println(line);
String[] fields = line.split(",");
addRecordFromFields(fields);
line = filein.readLine();
}
filein.close();
}
/**
* Loads the default library and provides for interaction with the data
* via the JPanel GUI inputs.
* #param args
* #throws IOException
*/
public String processData(String input, int selection, URL url)
{
//Create the main library object
PersonnelDatabase dbiLib = new PersonnelDatabase();
System.err.println(url);
// Try to read the default library
try
{
dbiLib.initDBFromFile(url);
}
catch (IOException e)
{
System.err.println("File IO Error");
e.printStackTrace();
System.exit(1);
}
// Queries can be simulated by typing into the console in Eclipse, and using Ctrl-d (Ctrl-z in Windows) when finished.
// For example: "searchLastName,Smith" would print a list of all people with the last name of Smith.
Iterable<Record> result = null;
String[] fields = new String[2];
if (input.contains(",")) {
fields = input.split(",");
}
switch(selection) {
case 0: result = dbiLib.searchByFirstName(input); break;
case 1: result = dbiLib.searchByLastName(input); break;
case 2: result = dbiLib.searchByFullName(fields[0].trim(), fields[1].trim()); break;
case 3: result = dbiLib.searchByCity(input); break;
case 4: result = dbiLib.searchByState(input); break;
case 5: result = dbiLib.searchByCityState(fields[0].trim(), fields[1].trim()); break;
case 6: result = dbiLib.searchByZip(input); break;
case 7: result = dbiLib.searchByPhoneNumber(input); break;
case 8: String[] newFields = new String[fields.length-1];
System.arraycopy(fields, 1, newFields, 0, fields.length-1);
dbiLib.addRecordFromFields(newFields);
return "Record added successfully!\nEnter a query or add another record.";
default: return "Invalid query.\nEnter another query or add a record.";
}
PersonnelDatabaseApplet class (initializes GUI, gathers input, and displays output):
public void init() {
/* Create and display the applet */
try {
java.awt.EventQueue.invokeAndWait(new Runnable() {
#Override
public void run() {
initComponents();
}
});
} catch (Exception e) {
System.err.println("Creation of GUI did not successfully complete.");
}
}
// Process inputs in the background.
SwingWorker worker = new SwingWorker<String, Void>() {
#Override
public String doInBackground() {
URL url = null;
try {
url = new URL(getCodeBase(), fileToRead);
}
catch(MalformedURLException e){}
personnelDatabase = new PersonnelDatabase();
final String output = personnelDatabase.processData(input, selection, url);
return output;
}
#Override
public void done() {
processingLabel.setVisible(true);
try {
textToDisplay = get(15, TimeUnit.SECONDS);
} catch (InterruptedException ignore) {
ignore.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
} catch (ExecutionException e) {
String why = null;
Throwable cause = e.getCause();
if(cause != null) {
why = cause.getMessage();
cause.printStackTrace();
} else {
why = e.getMessage();
e.printStackTrace();
}
System.err.println("Error retrieving request: " + why);
}
if(worker.isDone() && textToDisplay != null) {
processingLabel.setVisible(false);
outputTextArea.setText(textToDisplay);
}
}
};
private void searchButtonActionPerformed(java.awt.event.ActionEvent evt) {
selection = searchComboBox.getSelectedIndex();
input = valueTextField.getText();
processingLabel.setVisible(true);
worker.execute();
}
Link to the Applet on my personal website: http://www.ryan-taylor.me/Applied%20Maps/build/PersonnelDatabaseApplet.html
I'm fairly certain the error has nothing to do with the excel data itself as this program runs just fine in NetBeans and when running the html on my local machine. I'm guessing it has something to do with Swing (threads), but I'm not sure. I made changes to help with transferring data between Swing threads by making use of the SwingWorker, but I had no luck. I guess there's always the possibility I missed something when implementing it.
I also thought about signing the jar, but the file that I'm processing is stored online - not a local machine - so I didn't see a real need.
If anyone has any suggestions, I would greatly appreciate it!

Looks like the array index that's out of bounds is 3, because the input line contains only three fields and you're trying to access the fourth one (index 3) without checking to verify that it actually exists. The error is in
thisRecord.setCity(fields[3]);
because the array fields has only three elements. At
String[] fields = line.split(",");
addRecordFromFields(fields);
when you get to
Patsy,Hart,661 East 11th St.
array fields will be created with only 3 entries.
If the number of fields is expected to be constant then you should reject input lines that don't have the right number of fields. If the number of fields can vary, then you must check the actual number returned and extract only those elements that actually exist.

It looks like something is causing the file to be truncated when you run the applet in a browser. My guess is that you are fetching the file from a web server, and either the server or the browser is silently enforcing some download limit. (Or may be the file got truncated when you uploaded it ...)

I suspect a data race between your worker and another thread that is exposed by network latency. Two things may bear closer scrutiny:
Using invokeAndWait() to initialize the GUI is reasonable, as long as no further processing is done on the initial thread.
Your worker is unusual in not invoking publish(), as a way to process() records on the event dispatch thread, for example.

Related

How to use OpenNLP parser models in an Android app?

I go through this link for java nlp https://www.tutorialspoint.com/opennlp/index.htm
I tried below code in android:
try {
File file = copyAssets();
// InputStream inputStream = new FileInputStream(file);
ParserModel model = new ParserModel(file);
// Creating a parser
Parser parser = ParserFactory.create(model);
// Parsing the sentence
String sentence = "Tutorialspoint is the largest tutorial library.";
Parse topParses[] = ParserTool.parseLine(sentence, parser,1);
for (Parse p : topParses) {
p.show();
}
} catch (Exception e) {
}
i download file **en-parser-chunking.bin** from internet and placed in assets of android project but code stop on third line i.e ParserModel model = new ParserModel(file); without giving any exception. Need to know how can this work in android? if its not working is there any other support for nlp in android without consuming any services?
The reason the code stalls/breaks at runtime is that you need to use an InputStream instead of a File to load the binary file resource. Most likely, the File instance is null when you "load" it the way as indicated in line 2. In theory, this constructor of ParserModelshould detect this and an IOException should be thrown. Yet, sadly, the JavaDoc of OpenNLP is not precise about this kind of situation and you are not handling this exception properly in the catch block.
Moreover, the code snippet you presented should be improved, so that you know what actually went wrong.
Therefore, loading a POSModel from within an Activity should be done differently. Here is a variant that takes care for both aspects:
AssetManager assetManager = getAssets();
InputStream in = null;
try {
in = assetManager.open("en-parser-chunking.bin");
POSModel posModel;
if(in != null) {
posModel = new POSModel(in);
if(posModel!=null) {
// From here, <posModel> is initialized and you can start playing with it...
// Creating a parser
Parser parser = ParserFactory.create(model);
// Parsing the sentence
String sentence = "Tutorialspoint is the largest tutorial library.";
Parse topParses[] = ParserTool.parseLine(sentence, parser,1);
for (Parse p : topParses) {
p.show();
}
}
else {
// resource file not found - whatever you want to do in this case
Log.w("NLP", "ParserModel could not initialized.");
}
}
else {
// resource file not found - whatever you want to do in this case
Log.w("NLP", "OpenNLP binary model file could not found in assets.");
}
}
catch (Exception ex) {
Log.e("NLP", "message: " + ex.getMessage(), ex);
// proper exception handling here...
}
finally {
if(in!=null) {
in.close();
}
}
This way, you're using an InputStream approach and at the same time you take care for proper exception and resource handling. Moreover, you can now use a Debugger in case something remains unclear with the resource path references of your model files. For reference, see the official JavaDoc of AssetManager#open(String resourceName).
Note well:
Loading OpenNLP's binary resources can consume quite a lot of memory. For this reason, it might be the case that your Android App's request to allocate the needed memory for this operation can or will not be granted by the actual runtime (i.e., smartphone) environment.
Therefore, carefully monitor the amount of requested/required RAM while posModel = new POSModel(in); is invoked.
Hope it helps.

CSV file truncated after download

The legacy J2EE application details :
JSP + Servlets(2.4)
Websphere Application Server 7.0
The view is using IE frames, core javascript and so on
The user's action :
User's search returning > 900 rows takes some time to display (NO pagination)
User then clicks on 'Download' button which again triggers a form submit.
Following is the code snippet that is executed in the action servlet :
public class DownloadFileEvent extends ActionGeneric {
java.text.SimpleDateFormat df_file = new java.text.SimpleDateFormat("yyyyMMdd_HHmmss");
public void run(HttpServletRequest request, HttpServletResponse response) throws Exception {
String errormsg = null;
StringBuffer LineBuffer = null;
// read parameters.
String _v = request.getParameter("view");
// Start traitment.
try {
// get sessions.
ServletOutputStream out = response.getOutputStream();
// Create title columns.
response.setContentType("application/csv");
response.setHeader("Content-Disposition", "inline; filename = " + getFilename(_v));
LineBuffer = new StringBuffer();
//Get the string response from some business method
//String v_wrk = getOutflow(request, _v).toString();
LineBuffer.append(v_wrk);
LineBuffer.append("\r\n");
out.print(LineBuffer.toString());
out.flush();
// end.
}// fin try
catch (Exception e) {
errormsg = e.getMessage();
} finally {
// to do.
}
}// end run.
}// fin class
The issue :
Since the 'Download' takes some time, the user moves to other screen
When he comes back, the 'Open/Save/Save As' prompt is there already for some time. Now when user saves/opens the file but instead of 900 rows, there are less than 100 rows
Surprisingly, if the open/save is done immediately, all the rows are downloaded
In the catch block, I had put a log but there is no exception anywhere
The issue is not simulated on my local machine(Windows, WAS 7) or in the SYSTEM test environment(Linux, WAS 8.5) but surfaces on ACCEPTANCE (WAS 7, Linux) and PRODUCTION(WAS 7, Linux). The ACCEPTANCE and PRODUCTION have load balancers, web server set up but NOT in systest or local
How shall I proceed ?
Try a high SendBufferSize in your web servers. If the client does not read while the dialog is up, this will prevent the webserver from seeing writes eventually block then timeout.

How to automate mainframe application using java

I know this question is asked many times.But i didnt get what i want.
I need to automate quick3270 which is used to connect to mainframe using java.
First let me tell you what i want.
I need my code to open quick3270.exe then open my saved session:---this is done.
Now, I have to send commands to the quick3270.Here comes the problem, I dont know how to send command to that software.
Third is I am using robot class.So that i can input:TAB,ENTER,F3 etc. inputs.
So, the whole thing is I want to send commands to quick3270. I need interval also.Like send one command then delay of 1 second then other and so on.
public static void main(String[] args) throws IOException, AWTException {
String exeloc = "C:\\Program Files\\Quick3270\\Quick3270.exe ";
// my saved session
String directory = "C:\\Users\\c111128\\Desktop\\Project\\xyz.ecf";
ProcessBuilder builder = new ProcessBuilder(new String[] { exeloc, directory });
// Starting the process
Process p = builder.start();
// For handling keyboard events
Robot robot = new Robot();
try {
robot.delay(2000);
// Passing enter key to top screen
robot.keyPress(KeyEvent.VK_ENTER);
robot.delay(4000);
// Here I want to write the command
//Command like:"teleview" which is used in mainframe
robot.delay(1000);
}
catch (Exception e) {
System.out.println("Second:" + e);
e.printStackTrace();
}
}
did you manage the Problem?
Via VBA you can send commands to Quick3270 this way:
Set Session = .ActiveSession
Set Screen = Session.Screen
Screen.SendKeys ("<Enter>")
Result = Screen.WaitForKbdUnlock
Screen.SendKeys ("<PF12>")
Screen.SendKeys ("<Enter>")
Result = Screen.WaitForKbdUnlock
Screen.SendKeys ("<PF12>")
Result = Screen.WaitForKbdUnlock
Result = Screen.WaitForCursor(4, 15)
QuickPutstring "1", 10, 2
Private Function QuickPutstring(ByVal PutstringText As String, Row As Long, Col As Long)
Screen.MoveTo Row, Col
Screen.Putstring PutstringText
End Function
Hope that helps...

How can I add URLs to crawler of crawler4j at random times during progress

I'm tackling to crawler4j.
http://code.google.com/p/crawler4j/
and simple test crawl a site was succeeded.
but I want to add URLs at random times during progress.
this code shows the following exception at second constructing CrawlController.
how can I add URLs during progress? or reuse CrawlController?
(also reuse case without re-constructing CrawlController was failed.)
any idea?
or other good crawler in Java?
edit:
since it might be a bug, I posted also to the page of crawler4j.
http://code.google.com/p/crawler4j/issues/detail?id=87&thanks=87&ts=1318661893
private static final ConcurrentLinkedQueue<URI> urls = new ConcurrentLinkedQueue<URI>();
...
URI uri = null;
while (true) {
uri = urls.poll();
if (uri != null) {
CrawlController ctrl = null;
try {
ctrl = new CrawlController("crawler");
ctrl.setMaximumCrawlDepth(3);
ctrl.setMaximumPagesToFetch(100);
} catch (Exception e) {
e.printStackTrace();
return;
}
ctrl.addSeed(uri.toString());
ctrl.start(MyCrawler.class, depth);
}else{
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:638)
at edu.uci.ics.crawler4j.crawler.PageFetcher.startConnectionMonitorThread(PageFetcher.java:124)
at edu.uci.ics.crawler4j.crawler.CrawlController.<init>(CrawlController.java:77)
As of version 3.0, this feature is implemented in crawler4j. Please visit http://code.google.com/p/crawler4j/source/browse/src/test/java/edu/uci/ics/crawler4j/examples/multiple/ for an example usage.
Basically, you need to start the controller in non-blocking mode:
controller.startNonBlocking(MyCrawler.class, numberOfThreads);
Then you can add your seeds in a loop. Note that you don't need to start the controller several times in a loop.

Is there a good way to persist printer settings in a Swing app?

We are using the new Java printing API which uses PrinterJob.printDialog(attributes) to display the dialog to the user.
Wanting to save the user's settings for the next time, I wanted to do this:
PrintRequestAttributeSet attributes = loadAttributesFromPreferences();
if (printJob.printDialog(attributes)) {
// print, and then...
saveAttributesToPreferences(attributes);
}
However, what I found by doing this is that sometimes (I haven't figured out how, yet) the attributes get some bad data inside, and then when you print, you get a white page of nothing. Then the code saves the poisoned settings into the preferences, and all subsequent print runs get poisoned settings too. Additionally, the entire point of the exercise, making the settings for the new run the same as the user chose for the previous run, is defeated, because the new dialog does not appear to use the old settings.
So I would like to know if there is a proper way to do this. Surely Sun didn't intend that users have to select the printer, page size, orientation and margin settings every time the application starts up.
Edit to show the implementation of the storage methods:
private PrintRequestAttributeSet loadAttributesFromPreferences()
{
PrintRequestAttributeSet attributes = null;
byte[] marshaledAttributes = preferences.getByteArray(PRINT_REQUEST_ATTRIBUTES_KEY, null);
if (marshaledAttributes != null)
{
try
{
#SuppressWarnings({"IOResourceOpenedButNotSafelyClosed"})
ObjectInput objectInput = new ObjectInputStream(new ByteArrayInputStream(marshaledAttributes));
attributes = (PrintRequestAttributeSet) objectInput.readObject();
}
catch (IOException e)
{
// Can occur due to invalid object data e.g. InvalidClassException, StreamCorruptedException
Logger.getLogger(getClass()).warn("Error trying to read print attributes from preferences", e);
}
catch (ClassNotFoundException e)
{
Logger.getLogger(getClass()).warn("Class not found trying to read print attributes from preferences", e);
}
}
if (attributes == null)
{
attributes = new HashPrintRequestAttributeSet();
}
return attributes;
}
private void saveAttributesToPreferences(PrintRequestAttributeSet attributes)
{
ByteArrayOutputStream storage = new ByteArrayOutputStream();
try
{
ObjectOutput objectOutput = new ObjectOutputStream(storage);
try
{
objectOutput.writeObject(attributes);
}
finally
{
objectOutput.close(); // side-effect of flushing the underlying stream
}
}
catch (IOException e)
{
throw new IllegalStateException("I/O error writing to a stream going to a byte array", e);
}
preferences.putByteArray(PRINT_REQUEST_ATTRIBUTES_KEY, storage.toByteArray());
}
Edit: Okay, it seems like the reason it isn't remembering the printer is that it isn't in the PrintRequestAttributeSet at all. Indeed, the margins and page sizes are remembered, at least until the settings get poisoned at random. But the printer chosen by the user is not here:
[0] = {java.util.HashMap$Entry#9494} class javax.print.attribute.standard.Media -> na-letter
[1] = {java.util.HashMap$Entry#9501} class javax.print.attribute.standard.Copies -> 1
[2] = {java.util.HashMap$Entry#9510} class javax.print.attribute.standard.MediaPrintableArea -> (10.0,10.0)->(195.9,259.4)mm
[3] = {java.util.HashMap$Entry#9519} class javax.print.attribute.standard.OrientationRequested -> portrait
It appears that what you're looking for is the PrintServiceAttributeSet, rather than the PrintRequestAttributeSet.
Take a look at the PrintServiceAttribute interface, and see if the elements you need have been implemented as classes. If not, you can implement your own PrintServiceAttribute class(es).

Categories

Resources