Thursday, October 08, 2009

The right way to call an external process in Java

He it is... (one way to be sure everything goes well with your process)

Runtime currentRuntime = Runtime.getRuntime();
Process process = currentRuntime.exec();
// always handle the process output/error streams (java uses a small
// buffer to read the output of a process; if this buffer gets
// filled, the process waitFor() hangs)
// catch any potential error message from the process
StreamConsumer errorConsumer = new StreamConsumer(process.getErrorStream(), OutputType.ERR);
// catch any potential output
StreamConsumer outputConsumer = new StreamConsumer(process.getInputStream(), OutputType.OUT);
// start consuming...
errorConsumer.start();
outputConsumer.start();
int exitValue = process.waitFor();
// assume everything is okay...
assert exitValue == 0 : "Process returned " + exitValue;


And the code for StreamConsumer

static class StreamConsumer extends Thread {
InputStream is;
OutputType type;

StreamConsumer(InputStream is, OutputType type) {
this.is = is;
this.type = type;
}

@Override
public void run() {
try {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
switch (type) {
case ERR:
System.err.println(line);
break;
case OUT:
System.out.println(line);
break;
default:
assert false : type;
break;
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}

Friday, November 30, 2007

A great java debugger

I was stuck fro more than two days with an extremely annoying problem that only happened on client’s side. Obviously there are no development tools located on the client's server and obviously I can't force the customer to buy licenses for any commercial software that I might need to solve the problem. I knew although that the answer was somewhere... on ... Google. And here is what I found: "JSwat is a graphical Java debugger front-end, written to use the Java Platform Debugger architecture and based on the NetBeans Platform. JSwat is open-source software and is freely available in both binary and source code form. Its features include sophisticated breakpoints; colorized source code display with code navigator; byte code viewer; movable display panels showing threads, call stack, visible variables, and loaded classes; command interface for more advanced features; and Java-like expression evaluation, including method invocation." I've just installed it and now I'm setting the class paths to the application I plan to debug. It looks like a great tool 'till now and is quite intuitive. Enjoy it.

Monday, November 19, 2007

eLiberatica second edition

30th - 31st May 2008 (Friday-Saturday), Sofitel Hotel - Bucharest, Romania
Following the huge public success the first edition of eLiberatica gained in 2007, the second edition will continue in the same tradition: to gather community and business leaders around the world to talk about the hottest Open and Free Technologies topics.
eLiberatica has its unique spirit and identity; you will learn and discover new things, meet international IT personalities, business people, high-tech professionals, you will make new friends, new partners, celebrate and truly enjoy a live event.
eLiberatica 2008 is intended to focus on these main concepts:
• Business adoption - how to make/save money and gain profit using Open and Free Technologies;
• Government, administration and public schools - the importance of Open and Free Technologies;
• Professional growth participating in the FLOSS (Free/Libre/Open Source Software) community;
• Break the code - tips and tricks, things you will not find in IT books.
For more information you can check http://eliberatica.ro/ website.

Thursday, October 11, 2007

BigDecimal problems: Rounding error in BigDecimal.setScale

According to SUN’s documentation :http://java.sun.com/j2se/1.4.2/docs/api/java/math/BigDecimal.html#ROUND_HALF_UP this should be “the rounding mode that most of us were taught in grade school.” Surprisingly… it is not (or maybe I went to a different school). Check the examples:

import java.math.*;
public class BigTest {
public static void main(String[] args) {

BigDecimal bd = new BigDecimal(0.115);
bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println("? 0.12 = " + bd);

bd = new BigDecimal(1.115);
bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println("? 1.12 = " + bd);

bd = new BigDecimal(2.115);
bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);

System.out.println("? 2.12 = " + bd);
}
}




The issue was reported as a bug on SUN’s web site (4508009) and it was closed back in 2001 with the following comment:
“A side-effect of floating-point decimal -> binary conversion is being seen. The value indicated by the decimal string is not exactly representable. Using the string constructor instead avoids this particular issue.”
Although the workaround works this is still a bug.

Wednesday, August 22, 2007

Shortest manual for creating servlets

Step 1.
In order to create a servlet for a Web application, you will most often begin by extending HttpServlet and overriding one of the service methods. If you want to respond to the GET method, you will override doGet(). Similarly, if you want to respond to the POST method, you will override doPost().
Step 2.
You can process requests using methods defined in HttpServletRequest and related classes and interfaces. This enables you to use information included in the header that you don't see as well as information included in the URL. You can determine the HTTP method used to make the request and the cookies that the client has sent as well as information about the user, session, and path.
Step 3.
You can generate responses using methods defined in HttpServletResponse and related classes and interfaces. You can use these methods to create a cookie, send error messages, and set status codes. You can rewrite the URL and manipulate the contents of the buffer. Also, HttpServletResponse inherits from ServletResponse which contains the getWriter() and setContentType() methods that enable you to set the type of the content you are returning to the client and provide you with a handle to the PrintWriter that you use to do it.
Step 4.
You can pass information among servlets within the same context by setting and getting attributes. You can also write information to a file or database that can be accessed by other servlets.
Step 5.
Filters are new with the Servlet API 2.3. They enable you to pre− and post−process servlets. You can change a request before the servlet handles it or change the response (just not the body) after the servlet generates it. You can also include content from another resource using include() and forward the results of one servlet to another resource using forward().

Source: Java 2 Bible Enterprise Edition (read the book, is one of the best)

Thursday, June 21, 2007

Showing Modal Dialogs from Applets

Problem:
In order to access a JDialog component in any environment including the Applet specific environment you need to have access to a so called parent frame (java.awt.Frame) which is passed to the JDialog constructor and becomes the dialog owner. If this is never a problem in a desktop application where the application window itself is a frame, is quite annoying in an Applet specific environment.

Solution proposed by most java books:
Create a dummy frame.
JFrame f = new JFrame();
JDialog d = new JDialog(f);……..


Problems with the proposed solution:
Well, first of all it looks a little bit silly and I don’t see a point in creating frames all over the place. Second and way more important, when closing the dialog this tends to give the focus back to its owner and… surprise!. Since is owner is a brand new frame, nowhere to be found in the browser window the browser looses focus and it gets minimized.

Better solution:
Get the top level frame for the applet (yes, there is one, a Window, Frame or Dialog and the applet always returns a frame). Below is the piece of code that searched for the top level frame:


private Frame findParentFrame(){
Container container = this;
while(container != null){
if (container instanceof Frame)
return (Frame) container;

container = container.getParent();
}
return (Frame)null;
}


Obs. : Although it might seem so, getTopLevelAncestor method invoked on the Applet does not give the correct result.

Friday, June 08, 2007

AXIS and LOG4J performance issues

I’m working at a problem for couple of days. I have a web service (C#) installed on IIS and I’m calling it from a java servlet (on IB.M. Websphere 6.1). Everything works perfect on my side but hangs for about 30 minutes on client’s server.

After consuming all the possible causes for the problem that I could’ve think about:
- IIS installation issues;
- Web service installation
- Servlet / war installation
- and so on….
The problem was still there.

…and it would have been there forever but, by mistake, I noticed that the size of the logs folder is increasing dramatically with every call to the service. I checked my lig4j.properties and noticed that it had a DEBUGG level set for AXIS classes. This is creating Mbytes of log files !!! and is slowing the application in such a way that my websphere connections expire. During my last tests (with DEBUG level set for the entire AXIX module I stopped the process whet the log files size exceeded 25Mbytes. I’ve adjusted the configuration to:
· log4j.logger.org.apache.axis=DEBUG
· log4j.logger.org.apache.axis.encoding=INFO
· log4j.logger.org.apache.axis.utils=INFO
· log4j.logger.org.apache.axis.message=INFO
and the log files grew to a total of 2.4Mbytes (10 times smaller).
The actual transferred XML file is written in the logs (lol – had no idea).

I finally changed the log4j.properties to INFO for the entire AXIS module:
· log4j.logger.org.apache.axis=INFO
and everything works perfect.

I’m still wondering although why the big performance leak on DEBUGG mode ?