Updating different sheets of Apache POI Workbook using multiple threads - java

I have a for loop which i would like to run parallelly.
if (platform != null) {
for (final String p : platform) {
log.info("Platform " + p);
executorService.submit(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
runService(p, config, url, title, report);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
executorService.shutdown();
executorService.awaitTermination(Long.MAX_VALUE,TimeUnit.NANOSECONDS);
}
The runService method for each platform creates a new sheet for the same workbook.
I have read on other stackoverflow questions that apache poi workbook does not support multithreading on the same workbook object .I have made those methods as synchronized which are updating the sheet of the workbook. This solves all the apache-poi errors which I was getting but still would like to know is there a better way to handle this situation.

Related

Retrieving Excel cell contents returns NullPointerException

I'm trying to read the contents of an excel worksheet but my method keeps throwing an exception. I've tried everything to no avail but i'm sure that its a very minor detail that i'm not seeing. Could someone look at my code with a fresh pair of eyes and possibly point me out to what i'm doing wrong. Thanks!
/**
* This method sets the path to the excel file and the excel sheet as well as
* initializing the stream
*/
public static void setExcelFile(String path, String sheetName) {
try {
FileInputStream excelFile = new FileInputStream(path);
workbook = new XSSFWorkbook(excelFile);
worksheet = workbook.getSheet(sheetName);
}
catch (Exception e) {
e.printStackTrace();
}
}
/**
* This method reads the cell data from the excel file
*/
public static String getCellData(int rowNum, int colNum) {
try {
//This is what is causing my nullpointerexception according to eclipse
row = worksheet.getRow(rowNum);
//cell = worksheet.getRow(rowNum).getCell(colNum);
cell = row.getCell(colNum);
String cellData = cell.getStringCellValue();
return cellData;
}
catch (Exception e) {
e.printStackTrace();
return "Lactoferrin";
}
}
/**
* This is how i call both methods
*/
public static void main(String[] args) {
try {
ExcelUtility.setExcelFile(PATHTOTESTDATA, FILENAME);
String cellContents = ExcelUtility.getCellData(1,0);
System.out.println(cellContents);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Found it. I had saved the excel file within a package with the class files and eclipse could not find it...I do not know why. So i moved it into a folder at the root of the project and it worked.

PDFBox not printing text

I am attempting to print Word documents generated using docx4j that I convert to PDF and print using PDFBox. The document I'm attempting to print just contains a simple table with basic English text.
This is the method I use:
private void printDocument(){
PrinterJob job = PrinterJob.getPrinterJob();
try {
PDDocument document;
document = PDDocument.load("files\\textDocs\\OITScanSheet.pdf");
job.setPageable(new PDPageable(document, job));
job.setJobName("OIT Scan Sheet");
job.print();
} catch (NullPointerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (PrinterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
This is what I'm trying to print:
Before print
And this is what comes out when I print (Sorry for the terrible quality):
After print
The table is intact with the correct number of rows, but the text is not there. When I print the document from Adobe Reader it prints as it should.
I'm using PDFBox 2.0.0-snapshot right now. I switched from version 1.8.4 because I was running into this problem, where it was printing the table correctly but all of the text was junk.
I'm fairly certain the problem has something to do with some sort of font problem behind the scenes, but I have no idea how to go about fixing it. Any help would be greatly appreciated.
If you really need the printDialog, this is a ready to use code, assuming you have PDFBox 2.0 and font 2.0 in your classpath
public static void PDFPrintingServices(String filePath) throws IOException, PrinterException {
PrintRequestAttributeSet attr_set = new HashPrintRequestAttributeSet();
attr_set.add(MediaSizeName.ISO_A4);
attr_set.add(Sides.ONE_SIDED);
PDDocument pdf = PDDocument.load(new File(filePath));
PDFPageable p = new PDFPageable(pdf);
PDFPrintable printable = new PDFPrintable(pdf, Scaling.SCALE_TO_FIT);
PrinterJob job = PrinterJob.getPrinterJob();
job.setJobName("My Printer");
job.setPageable(p);
job.setPrintable(printable);
if(job.printDialog()) {
job.print();
job.print(attr_set);
}
}

Execute multiple tasks on async task or in async task, and return data from postexecute

I have an API that I use to retrieve daily schedules on the live cable-tv for various channels. I have a scenario in which I need a guidance as to which approach should work here.
Lets say I need schedules for 10 different channels from the API.
Should I execute 10 different async tasks for the retrieval of the required data?
Problem:
How would I collect the data in an arraylist and return it once all execution is completed?
How will I access the arraylist in my main function once onpostexecute returns the result?
Or I should just provide the list of channels to my single async task and make it build a single output of arraylist for my main function invoking it?
Problem:
Since I will be accessing a webservice for this purpose, will it make it run slow as compared to my 1st approach?
Second problem with this approach is the same as I am having with my 1st one, I need to know when and how to get the complete resultset once the execution of the task is completed?
Here is some code to explain the problem:
//going with the first approach
//invoking my asynctask from an activity or another class
//I need a global arraylist which I can use after postexecute returns its result
ArrayList<String> channels = channelManager.getAllChannelsByRegion("xyz");
final ArrayList<ChannelSchedule> schedules = new ArrayList<ChannelSchedule>();
final ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
for (int i = 0; i < channels.size(); ++i){
AsyncInvokeURLTask task = null;
try {
task = new AsyncInvokeURLTask(
channels.get(i), context, new AsyncInvokeURLTask.OnPostExecuteListener() {
#Override
public void onPostExecute(String result) {
// TODO Auto-generated method stub
try {
//Need to add results to arraylist here...But cannot know when it ends completely
ChannelSchedule schedule = mapper.readValue(result, ChannelSchedule.class);
Log.v("channel name", schedule.getChannelName());
Log.v("channel date", schedule.getDate());
Log.v("channel thumb", schedule.getListOfShows().get(0).getShowThumb());
Log.v("channel time", schedule.getListOfShows().get(0).getShowTime());
} catch (JsonParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JsonMappingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
task.execute();
}
Please let me know if something is not clear or missing.
Launching 10 AsyncTask is perfectly fine.
You can keep a count of the number of pending requests. As OnPostExecute is run on the UI thread there are no risks of race condition.
private int numberOfPendingRequests;
public void MyFunc() {
ArrayList<String> channels = channelManager.getAllChannelsByRegion("xyz");
final ArrayList<ChannelSchedule> schedules = new ArrayList<ChannelSchedule>();
final ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
numberOfPendingRequests = channels.size();
for (int i = 0; i < channels.size(); ++i) {
schedules.add(null);
}
for (int i = 0; i < channels.size(); ++i) {
AsyncInvokeURLTask task = null;
final int index = i; // final so it can be used in the onPostExecute.
try {
task = new AsyncInvokeURLTask(
channels.get(i), context, new AsyncInvokeURLTask.OnPostExecuteListener() {
#Override public void onPostExecute(String result) {
try {
ChannelSchedule schedule = mapper.readValue(result, ChannelSchedule.class);
Log.v("channel name", schedule.getChannelName());
Log.v("channel date", schedule.getDate());
Log.v("channel thumb", schedule.getListOfShows().get(0).getShowThumb());
Log.v("channel time", schedule.getListOfShows().get(0).getShowTime());
schedules.set(index, schedule);
numberOfPendingRequests--;
if (numberOfPendingRequests == 0) {
// Everything is received, do stuff here.
}
} catch (JsonParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JsonMappingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
task.execute();
}
}

Taking input from console in a plugin in java

I am developing an Eclipse plugin and I want to take input from the user. I had a problem before with dealing with the console as I have 2 consoles 1 in the original Eclipse application and the other in the new opened Eclipse plugin window. I used the method shown below to print in the Console of the Plugin
public static void writeToConsole(String output) {
MessageConsole console = new MessageConsole("My Console", null);
console.activate();
ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[]{ console });
MessageConsoleStream stream = console.newMessageStream();
stream.println(output);
}
I just don't know how to write in the console and take what's written in a variable
N.B.
The normal methods like
BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in));
String s = bufferRead.readLine();
System.out.println(s);
are working for the original Eclipse not the plugin
You can't tie up the UI waiting for user input so you have to handle user input when it is received. One way to do this is with a document listener. Here is an example that prints the last line typed:
console.getDocument().addDocumentListener(new IDocumentListener() {
#Override
public void documentChanged(final DocumentEvent event) {
if ("\r\n".equals(event.getText())) {
final IDocument doc = event.getDocument();
try {
final IRegion region = doc.getLineInformationOfOffset(event.getOffset());
try {
final String line = doc.get(region.getOffset(), region.getLength());
System.out.println(line);
} catch (BadLocationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (BadLocationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
#Override
public void documentAboutToBeChanged(final DocumentEvent event) {
// TODO Auto-generated method stub
}
});

Java event is killed when a function for audio playing is called

I am facing a strange programming problem. It has exhausted me but with no solution found!
My program is mainly dependent on an event (Java Listener) that is fired from an external hardware for receiving an audio message from that hardware.Inside the eventHandler i do the following
pass the received message to a static method "decode" from another class which returns data
then I open FileOutputStream, write these data "audio" to a file,and close the FileOutputStream.
I call a static method "play" from another class to play the audio file.
The problem is: whenever the method "Play" is called for the first time, it executes correctly but it causes the event to stop raising and the program to terminate but without exceptions. When I comment out the play method, everything becomes okay!
Do you have some idea about a method causing program termination ?
public void messageReceived(int to,Message message)
{
speexAudioMsg msg = (speexAudioMsg)message;
try{
byte[] output = jspeexDecoder.decode(msg.get_frame());
os = new FileOutputStream(file);
os.write(output);
os.close();
Player.play();
}
catch (IOException ex) {ex.printStackTrace();}
}
You are probably using the event thread to play the music. Try calling Player.play() in a new thread.
new Thread(new Runnable() { public void run() {Player.play()}}).start();
here is an example:
static String url = "http://www.stackoverload.com";
public static void threadTest() {
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
URL url2 = new URL(url);
url2.openStream();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).run();

Categories

Resources